Contact


    Thank you

    We will be in contact shortly.

    Single Page Applications and kdb+: Vue

    8 June 2021
    Share this:

    By Stephen Trainor

    This blog post is the fourth of a series, which demonstrates how different front-end technologies can be used with kdb+. The technology discussed in this post is called Vue (also known as vue.js). Vue is an open-source JavaScript (JS) framework which was first released in 2014. Version 3.0 was released in September 2020, which is covered in this post. A distinguishing feature of Vue is that HTML, JS and CSS can be stored in a single .vue file, rather than the traditional approach of maintaining JS and HTML files separately.

    The Single-Page Application (SPA) discussed in this blog contains two tabs. The first is a calendar, which demonstrates cell editing and pagination. The second doesn’t contain any functionality and is just present to demonstrate URL routing for this technology.

    Common SPA Features

    Websockets and Promises are used throughout all of the technologies in this series, and are discussed in the first entry, which focuses on React and is posted on this link. It also provides a brief introduction to what a Single-Page Application is.

    Vue

    Setting up

    • Download source code from Github
    • Download npm
    • Run npm update in the terminal from the vueProject directory, to install dependencies from package.json (bringing the project size to around 130MB)
    • Run downloaded startV.bat and startQ.bat files – if you aren’t using C:\q\w64, startQ will require editing
    • View from a browser: http://localhost:8080/

    Components and data-flow

    The philosophy of Vue is to have .vue components, each containing HTML, JS and scoped-css, which neatly organise styling and dependencies.

    Data can be passed from parent components to child components as props, and child components emit events which can trigger callbacks in the parents. Prop-types can be used to document components and provide warnings in the console if an incorrectly typed prop is provided to the component.

    Vue also allows developers to write reactive code, in which HTML is only re-rendered if the associated refs are updated..

    Directives

    Vue comes with many predefined directives, which allow the developer to simply generate the desired HTML. Some directives used in this project are explained below. The full list can be found here.

    • v-if
      • Renders an element if the expression evaluates to true
    • v-else
      • Renders an element if the previous v-if evaluates to false
    • v-for
      • Renders an element one time for each item in the provided data
    • v-on:click
      • Calls a function when the element is clicked
    • v-on:blur
      • Calls a function when the element loses focus
    • v-bind
      • Binds an attribute to the element. Eg a dynamic class
    • v-model
      • Creates a two-way data binding on an element or component. Eg a checkbox which updates a boolean variable when it is clicked

    “@” can also be used as a shorthand for “v-on:”, but is potentially less readable.

    The below directives were also considered for this project, but were unsuitable as the use-case was to detect events anywhere on the page, whereas these directives only detect events within the element they’re attached to.

    • v-on:wheel
      • Calls a function when the user scrolls
    • v-on:keydown.ip/down/left/right
      • Calls a function when the user presses the directional keys

    Libraries

    primevue is a UI component library which was used for the TabMenu and ProgressSpinner components

    vue-devtools is a browser extension which allows developers to inspect vue components and data using Chrome dev tools

    vue-router enables predefined url paths to load corresponding JS files

    Sample Project


    Vue SPA – Consists of a calendar with editable cells, and a separate tab to demonstrate routing

    Structure

    • main.js
      • App.vue
        • TabMenu
        • router-view
          • Calendar.vue
          • OtherTab.vue

    main.js contains component registration and creates the application instance.

    App.vue contains the TabMenu to display the two tab buttons, and router-view, which renders the selected tab.

    Rendering a table

     

    kdb+

     

    In the calendar tab, a table with 8 rows is displayed on the front end, and refreshes as the user scrolls:

    .cal.getCalendar:{[index]
      t:update hiddenIndex:i from cal;
      select ["j"$index,8] from t
    };

     

    Vue

    <table v-else class="table">
    <thead>
    <tr>
    <th v-for="(column,i) in calendarKeys" v-bind:class="this.headerWidth(column)" :key="i">{{formatHeader(column)}}</th>
    </tr>
    </thead>
    <tbody>
    <tr v-for="(row,index) in calendar" :key="index">
    <td v-bind:contenteditable="isEditable(colName)" v-bind:class="this.highlightDate(calendar[index][colName], colName)" v-on:blur="editRow(index, colName, $event)"
    v-for="(colName) in calendarKeys" :key="colName">{{this.formatCell(calendar[index],colName)}}</td>
    </tr>
    </tbody>
    </table>

    Editing a table

     

    kdb+

     

    When the user edits a cell in the calendar tab, .cal.editRow is called. It formats the text provided by the user, and overwrites that table cell in memory using a functional select.

     

    .cal.editRow:{[index; kolName; kolVal]
      index:"j"$index;
      kolName:`$kolName;
      t:`cal;
      kolType:type (value t)[kolName];
      //Only include numbers in number fields
      if[kolType in "h"$5+til 5; kolVal@:where kolVal in .Q.n,"-."];
      //Cast to the appropriate datatype
      kolVal:(neg kolType)$kolVal;
      if[kolType=0h; kolVal:(enlist; kolVal)];
      if[kolType=11h; kolVal:enlist kolVal];
      //update kolName:kolVal from cal where i=index
      ![t; enlist(=;`i;index); 0b; (enlist kolName)!enlist kolVal];
    }

    Vue

     

    
    editRow: function(index, colName, event){
    let text = event.target.innerText;
    index+=this.index;
    this.qPromise(".cal.editRow",[index, colName, text]).then(this.postEditRow).catch(this.error)
    },

     

    Conclusion

     

    Vue is an SPA framework which is simple to set up and can provide a fast and responsive browsing experience. This blog discussed its benefits, such as built-in directives, two-way data-binding and custom components, and should serve as a suitable introduction to getting started with Vue and coupling it with kdb+.

    The front and back-end code outlined above are available in GitHub on this link