Create SpreadJS custom cells using VUE components

In the previous article, we introduced how to dynamically create spreadsheet components in Vue by setting runtimeCompiler to true. For details, please click here useVUE component creates SpreadJS custom cell (I).

However, in the actual scenario, we may only need to dynamically create VUE components, and the template content of components does not need to be dynamically loaded. In this case, autoComplete is a typical usage scenario.

autoComplete gives us the freedom to convert any input received into a tag & lt; input>,& lt; textarea> And elements with the contenteditable attribute. When keyboard entry is complete, the plug-in starts searching for matching entries and displays a list of values to choose from. By entering more characters, users can filter the list to better match.

stay Front end spreadsheet In, we can directly use it to select the content, such as entering the label of the article or entering the e-mail address in the address book.; Autocomplete can also be used to populate relevant information, such as entering city names and obtaining postal codes. Now, if we want to implement this function in the pure front-end table, we can solidify the dynamically created components, import them on demand, and then mount them.

This simplifies what we mentioned in the previous article. You need to start runtimeCompiler to implement it.

Next, let's introduce the specific methods:

  1. Encapsulate AutoComplete components
  <div>
    <el-autocomplete
      :style="cellStyle"
      popper-class="my-autocomplete"
      v-model="text"
      :fetch-suggestions="querySearch"
      placeholder="Please enter the content"
      :popper-append-to-body="false"
      value-key="name"
      @select="handleSelect"
    >
      <i
        class="el-icon-edit el-input__icon"
        slot="suffix"
        @click="handleIconClick"
      >
      </i>
      <template slot-scope="{ item }">
        <div class="name">{{ item.name }}</div>
        <span class="addr">{{ item.phone }}</span>
      </template>
    </el-autocomplete>
  </div>
</template>
  <script>

import DataService from '../static/dataService'

export default {
    props: ['text','cellStyle'],
    mounted() {
        this.items = DataService.getEmployeesData();
    },
    methods: {
        querySearch(queryString, cb) {
            var items = this.items;
            var results = queryString ? items.filter(this.createFilter(queryString)) : items;
            // Unable to set the location of dynamic content. gcUIElement can be added dynamically
            // setTimeout(() => {
            //   let popDiv = document.getElementsByClassName("my-autocomplete")[0];
            //   if(popDiv){
            //     popDiv.setAttribute("gcUIElement", "gcEditingInput");
            //   }
            // }, 500);
            // Call callback to return the data of the suggestion list
            cb(results);
        },
        createFilter(queryString) {
            return (restaurant) => {
            return (restaurant.name.toLowerCase().indexOf(queryString.toLowerCase()) === 0);
            };
        },
        handleSelect(item) {
            console.log(item);
        },
        handleIconClick(ev) {
            console.log(ev);
        }
    }
}
</script>
copy

What points need to be paid attention to

  • The component provides the text (or value) attribute, which is used to correspond to the value of the cell to be edited. If the component is not bound with model in both directions, it needs to actively update the text after the operation
  • Provide cellStyle, user CellType, and control the size of the component according to the cell size
  • If the injected DOM element of the component is not inside the template div, the gcUIElement attribute needs to be added. The reason is described in detail in the previous article

2. autoComplete mounts components directly without additional dynamic declarations

import AutoComplete from '../components/AutoComplete'

AutoComplateCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) {
    let width = cellRect.width > 180 ? cellRect.width : 180;
    if (editorContext) {
       // create component constructor
       const AutoCompleteCtor = Vue.extend(AutoComplete);
        this.vm = new AutoCompleteCtor({
        propsData: {
          cellStyle: {width: width+"px"}
        }
      }).$mount(editorContext.firstChild);
    }
};
copy

The rest of the code remains unchanged, which not only eliminates the need for runtimeCompiler, but also improves the maintainability of the code.

The two articles in this series introduce in detail two different ways to solve the problem that the components under the framework cannot be used directly under the framework page through template due to the problems of framework life cycle and custom cell rendering logic. We successfully solved this problem with Vue, and optimized it in the second way to effectively improve the maintainability of the code.

Posted by Gonwee on Mon, 09 May 2022 12:01:33 +0300