/vue-guspread

Guspread is a Simple Spreadsheet Component for Vue.js

Primary LanguageVueMIT LicenseMIT

Guspread Build Status

Guspread is a Javascript Spreadsheet Component for Vue.

demo-image

DEMO

https://misu007.github.io/vue-guspread/

Install

NPM

npm install vue-guspread

After installing, please register the component either globaly or localy you would like.

Global Registration

import VueGuspread from 'vue-guspread';
import 'vue-guspread/dist/vue-guspread.css';
Vue.use(VueGuspread);

Local Registration

import VGuspread from "vue-guspread";

export default {
  components: {
    VGuspread
  }
}

CDN

<v-guspread></v-guspread> tag will be available after loading the javascript library.

<link href="https://cdn.jsdelivr.net/npm/vue-guspread@latest/dist/vue-guspread.css" rel="stylesheet"/>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-guspread@latest"></script>

Get Started

npm

<template>
  <div style="width:100%;height:400px;">
    <v-guspread v-model="dataset" :fields="fields"></v-guspread>
  </div>
</template>

<script>
import VGuspread from "vue-guspread";

export default {
  components: {
    VGuspread
  },
  data: () => ({
    fields: [
      { name: "c1", label: "A" },
      { name: "c2", label: "B" },
      { name: "c3", label: "C" }
    ],
    dataset: [
      { c1: "blue", c2: "banana", c3: "sky" },
      { c1: "red", c2: "apple", c3: "river" },
      { c1: "orange", c2: "orange", c3: "mountain" },
      { c1: "white", c2: "rasberry", c3: "lake" }
    ]
  })
};
</script>

CDN

<!DOCTYPE html>
<html>
    <head>
        <title>Guspread Sample</title>
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui"/>
        <link href="https://cdn.jsdelivr.net/npm/vue-guspread@latest/dist/vue-guspread.css" rel="stylesheet"/>
    </head>
    <body>
        <div id="app">
            <v-guspread v-model="dataset" :fields="fields"></v-guspread>
        </div>
        
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/vue-guspread@latest"></script>
        
        <script>
        new Vue({
            el: '#app',
            data: {
                fields: [
                    { name: "c1", label: "A" },
                    { name: "c2", label: "B" },
                    { name: "c3", label: "C" }
                ],
                dataset: [
                    { c1: "blue", c2: "banana", c3: "sky" },
                    { c1: "red", c2: "apple", c3: "river" },
                    { c1: "orange", c2: "orange", c3: "mountain" },
                    { c1: "white", c2: "raspberry", c3: "lake" }
                ]
            }
        });
        </script>
    </body>
</html>

Visualforce

<apex:page docType="html-5.0" applyHtmlTag="false" applyBodyTag="false" standardStylesheets="false" showHeader="false">
    <html xmlns:v-bind="http://vue.org" xmlns:v-on="http://vue.org" xmlns:v-slot="http://vue.org">
        <head>
            <title>Guspread Sample For Visualforce</title>
            <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui"/>
            <link href="https://cdn.jsdelivr.net/npm/vue-guspread@latest/dist/vue-guspread.css" rel="stylesheet"/>
        </head>
        <body>
            <div id="app">
                <v-guspread v-model="dataset" v-bind:fields="fields"></v-guspread>
            </div>
            
            <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
            <script src="https://cdn.jsdelivr.net/npm/vue-guspread@latest"></script>
            
            <script>
            new Vue({
                el: '#app',
                data: {
                    fields: [
                        { name: "c1", label: "A" },
                        { name: "c2", label: "B" },
                        { name: "c3", label: "C" }
                    ],
                    dataset: [
                        { c1: "blue", c2: "banana", c3: "sky" },
                        { c1: "red", c2: "apple", c3: "river" },
                        { c1: "orange", c2: "orange", c3: "mountain" },
                        { c1: "white", c2: "raspberry", c3: "lake" }
                    ]
                }
            });
            </script>
        </body>
    </html>   
</apex:page>

Usage

Props

Required Prop Name Type Description Default
* value (v-model) Array An array of row item objects []
* fields Array An array of column objects that each describe a header []
color String Apply css color ('#ffffff' or rgb(65, 184, 131)) to the main controled color. '#41b883'
nameKey String The value of this property represents the field key of each items 'name'
labelKey String The value of this property represents the default label of each fields 'label'
cellClass Function You can optionaly customize the classname for each cells null
cellReadonly Function You can optionaly apply readonly behavior for each cells null

Events

Event Name Payload Description
changeEditMode True (Edit mode) or False (Show mode) Fired when changed between edit mode and show mode
changeFocused {"a": Object, "b": Object} Fired when changed the rect focued cells. Both keys "a" and "b" have row index and col index

Slots

Slot Name Slot Props Description
field {"field": Object} "field": Each field Object given as "fields" prop
cell {"field": Object, "item": Object, "row": Number, "col": Number, "value": Any} "item": Each row Object given as "value(v-model)" prop
input {"field": Object, "item": Object}

Example

<template>
  <div style="width: 100%; height:600px;">
    <v-guspread
      v-model="dataset"
      :fields="fields"
      nameKey="apiName"
      :cellClass="cellClass"
      :cellReadonly="cellReadonly"
    >
      <!-- Each Field -->
      <template #field="{field}">{{field.label}}</template>
      <!-- Each Field -->

      <!-- Each Cell -->
      <template #cell="{field, item}">
        <!-- Checkbox-->
        <template v-if="field.dataType == 'Boolean'">
          <template v-if="item[field.apiName] == true">✅</template>
          <template v-else-if="item[field.apiName] == false">☐</template>
          <template v-else></template>
        </template>
        <!-- Checkbox-->

        <!-- Text-->
        <template v-else>
          <span>{{item[field.apiName]}}</span>
        </template>
        <!-- Text-->
      </template>
      <!-- Each Cell -->

      <!-- Input Form -->
      <template #input="{field, item}">
        <!-- Checkbox -->
        <template v-if="field.dataType == 'Boolean'">
          <input type="checkbox" v-model="item[field.apiName]" />
        </template>
        <!-- Checkbox -->

        <!-- Number-->
        <template v-else-if="field.dataType == 'Int'">
          <input type="number" v-model="item[field.apiName]" />
        </template>
        <!-- Number -->

        <!-- Text -->
        <template v-else>
          <input type="text" v-model="item[field.apiName]" />
        </template>
        <!-- Text -->
      </template>

      <!-- Input Form -->
    </v-guspread>
  </div>
</template>

<script>
export default {
  data: () => ({
    fields: [
      { dataType: "Boolean", label: "Field1", apiName: "c1", updateable: true },
      { dataType: "Int", label: "Field2", apiName: "c2", updateable: true },
      { dataType: "String", label: "Field3", apiName: "c3", updateable: false },
      { dataType: "String", label: "Field4", apiName: "c4", updateable: true }
    ],
    dataset: [
      { c1: true, c2: 58, c3: "Japan", c4: "Tokyo" },
      { c1: false, c2: 30, c3: "US", c4: "New York" },
      { c1: true, c2: 48, c3: "China", c4: "Beijing" },
      { c1: false, c2: 27, c3: "UK", c4: "London" },
      { c1: true, c2: 75, c3: "Korea", c4: "Seoul" }
    ],
    cellClass: ({ field }) => {
      let ret = [];
      if (field.dataType == "Boolean" || field.dataType == "Int") {
        ret.push("text-align-right");
      }
      return ret;
    },
    cellReadonly: ({ field }) => {
      return !field.updateable;
    }
  })
};
</script>

<style lang="stylus">
.guspread-table {
  .guspread-table-cell.text-align-right {
    text-align: right;
  }
}
</style>