Uibuilder Table Implementation

Hello, I'm brand new to working with vue and web development so please bear with me. I'm working on a project that is using the standard dashboard, but I want to be able to keep that dashboard secured and not publicly accessible. I'm currently doing this using a reverse proxy and Authelia (works great). Now I want to create a page that is publicly accessible without a login to display data from a table. I have installed uibuilder and am excited about the potential, but am banging my head against my desk trying to use the tables built into bootstrap vue to display my data. (here)
I have deployed the standard example page and installed bootstrap and bootstrap vue using the Front-End-Library-Manager.
I am unable to get the table to display on the page when I edit the html to include the example code. I'm certain I'm missing something silly and am hoping someone can point me in the right direction or even better post an example of how to use the bootstrap tables with incoming msg data. I haven't tried to add the incoming data to the table myself because I'm not currently able to get the table to even display. I was trying to take things one step at a time, but I thought it best to describe my ultimate goal so the scope is clear for this post.

The incoming data is being pulled from a database and sent into the uibuilder node, it is formatted like this:
[{"ROWID":11,"EXACTTIME":"Friday_June11th2021_5:22:42pm","TIMESTAMP":"Friday, June 11th 2021, 5:22 pm","FIRSTNAME":"Wells","LASTNAME":"Fargo"},{"ROWID":10,"EXACTTIME":"Friday_June11th2021_5:17:46pm","TIMESTAMP":"Friday, June 11th 2021, 5:17 pm","FIRSTNAME":"advance","LASTNAME":"auto"},{"ROWID":9,"EXACTTIME":"Friday_June11th2021_4:55:48pm","TIMESTAMP":"Friday, June 11th 2021, 4:55 pm","FIRSTNAME":"test","LASTNAME":"user"},{"ROWID":8,"EXACTTIME":"Friday_June11th2021_4:55:32pm","TIMESTAMP":"Friday, June 11th 2021, 4:55 pm","FIRSTNAME":"advance","LASTNAME":"auto"},{"ROWID":7,"EXACTTIME":"Friday_June11th2021_4:55:23pm","TIMESTAMP":"Friday, June 11th 2021, 4:55 pm","FIRSTNAME":"Wells","LASTNAME":"Fargo"},{"ROWID":6,"EXACTTIME":"Friday_June11th2021_4:48:24pm","TIMESTAMP":"Friday, June 11th 2021, 4:48 pm","FIRSTNAME":"Wells","LASTNAME":"Fargo"},{"ROWID":5,"EXACTTIME":"Friday_June11th2021_4:48:15pm","TIMESTAMP":"Friday, June 11th 2021, 4:48 pm","FIRSTNAME":"advance","LASTNAME":"auto"},{"ROWID":4,"EXACTTIME":"Friday_June11th2021_4:48:05pm","TIMESTAMP":"Friday, June 11th 2021, 4:48 pm","FIRSTNAME":"test","LASTNAME":"user"}]

If I haven't provided enough information please let me know, happy to provide more. Thanks for reading!

Flow :

[{"id":"4c55571eab755af4","type":"uibuilder","z":"affcf244.5a4cd","name":"","topic":"","url":"table","fwdInMessages":false,"allowScripts":false,"allowStyles":false,"copyIndex":true,"showfolder":false,"useSecurity":false,"sessionLength":432000,"tokenAutoExtend":false,"oldUrl":"uibuilder","reload":false,"credentials":{},"x":460,"y":560,"wires":[["eeafe87409b1a331"],[]]},{"id":"33f5b55cb3bf51a0","type":"inject","z":"affcf244.5a4cd","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"ROWID\":11,\"EXACTTIME\":\"Friday_June11th2021_5:22:42pm\",\"TIMESTAMP\":\"Friday, June 11th 2021, 5:22 pm\",\"FIRSTNAME\":\"Wells\",\"LASTNAME\":\"Fargo\"},{\"ROWID\":10,\"EXACTTIME\":\"Friday_June11th2021_5:17:46pm\",\"TIMESTAMP\":\"Friday, June 11th 2021, 5:17 pm\",\"FIRSTNAME\":\"advance\",\"LASTNAME\":\"auto\"},{\"ROWID\":9,\"EXACTTIME\":\"Friday_June11th2021_4:55:48pm\",\"TIMESTAMP\":\"Friday, June 11th 2021, 4:55 pm\",\"FIRSTNAME\":\"test\",\"LASTNAME\":\"user\"},{\"ROWID\":8,\"EXACTTIME\":\"Friday_June11th2021_4:55:32pm\",\"TIMESTAMP\":\"Friday, June 11th 2021, 4:55 pm\",\"FIRSTNAME\":\"advance\",\"LASTNAME\":\"auto\"},{\"ROWID\":7,\"EXACTTIME\":\"Friday_June11th2021_4:55:23pm\",\"TIMESTAMP\":\"Friday, June 11th 2021, 4:55 pm\",\"FIRSTNAME\":\"Wells\",\"LASTNAME\":\"Fargo\"},{\"ROWID\":6,\"EXACTTIME\":\"Friday_June11th2021_4:48:24pm\",\"TIMESTAMP\":\"Friday, June 11th 2021, 4:48 pm\",\"FIRSTNAME\":\"Wells\",\"LASTNAME\":\"Fargo\"},{\"ROWID\":5,\"EXACTTIME\":\"Friday_June11th2021_4:48:15pm\",\"TIMESTAMP\":\"Friday, June 11th 2021, 4:48 pm\",\"FIRSTNAME\":\"advance\",\"LASTNAME\":\"auto\"},{\"ROWID\":4,\"EXACTTIME\":\"Friday_June11th2021_4:48:05pm\",\"TIMESTAMP\":\"Friday, June 11th 2021, 4:48 pm\",\"FIRSTNAME\":\"test\",\"LASTNAME\":\"user\"}]","payloadType":"json","x":200,"y":560,"wires":[["4c55571eab755af4"]]},{"id":"eeafe87409b1a331","type":"debug","z":"affcf244.5a4cd","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":640,"y":560,"wires":[]}]

.

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <title>Node-RED UI Builder - VueJS + bootstrap-vue default template</title>
    <meta name="description" content="Node-RED UI Builder - VueJS + bootstrap-vue default template" />

    <link rel="icon" href="./images/node-blue.ico" />

    <link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap/dist/css/bootstrap.min.css" />
    <link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.css" />
    <!-- Your own CSS -->
    <link type="text/css" rel="stylesheet" href="./index.css" media="all" />
  </head>
  <body>
    <div id="app" v-cloak>
      <b-container id="app_container" class="mt-5">
        <h1>UIbuilder + Vue.js + bootstrap-vue table for Node-RED</h1>
        <div class="mt-5">
          <b-table striped hover small :items="items" sort-by="ROWID"></b-table>
        </div>
      </b-container>
    </div>

    <!-- These MUST be in the right order. Note no leading / -->

    <!-- REQUIRED: Socket.IO is loaded only once for all instances. Without this, you don't get a websocket connection -->
    <script src="../uibuilder/vendor/socket.io/socket.io.js"></script>

    <!-- Vendor Libraries - Load in the right order, use minified, production versions for speed -->
    <script src="../uibuilder/vendor/vue/dist/vue.js"></script>
    <!-- dev version with component compiler -->
    <!-- <script src="../uibuilder/vendor/vue/dist/vue.min.js"></script>   prod version with component compiler -->
    <!-- <script src="../uibuilder/vendor/vue/dist/vue.runtime.min.js"></script>   prod version without component compiler -->
    <script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.js"></script>
    <!-- Dev version -->
    <!-- <script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.min.js"></script>   Prod version -->

    <!-- REQUIRED: Sets up Socket listeners and the msg object -->
    <script src="./uibuilderfe.js"></script>
    <!-- dev version -->
    <!-- <script src="./uibuilderfe.min.js"></script>     prod version -->

    <!-- OPTIONAL: You probably want this. Put your custom code here -->
    <script src="./index.js"></script>
  </body>
</html>

index.js

/* jshint browser: true, esversion: 5, asi: true */
/*globals Vue, uibuilder */
// @ts-nocheck
/*
  Copyright (c) 2021 Julian Knight (Totally Information)

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/
"use strict";

/** @see https://totallyinformation.github.io/node-red-contrib-uibuilder/#/front-end-library */

// eslint-disable-next-line no-unused-vars
const app = new Vue({
  el: "#app",

  data() {
    return {
         items: []  // table data 
        
        };
  }, // --- End of data --- //

  computed: {}, // --- End of computed --- //

  methods: {}, // --- End of methods --- //

  // Available hooks: beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed, activated,deactivated, errorCaptured

  /** Called after the Vue app has been created. A good place to put startup code */
  created: function() {
    // Example of retrieving data from uibuilder
    this.feVersion = uibuilder.get("version");

    uibuilder.start();
  }, // --- End of created hook --- //

  /** Called once all Vue component instances have been loaded and the virtual DOM built */
  mounted: function() {
    //console.debug('[indexjs:Vue.mounted] app mounted - setting up uibuilder watchers')

    var app = this; // Reference to `this` in case we need it for more complex functions

    // If msg changes - msg is updated when a standard msg is received from Node-RED over Socket.IO
    uibuilder.onChange("msg", function(msg) {
      console.info('[indexjs:uibuilder.onChange] msg received from Node-RED server:', msg)
      app.items = msg.payload;  // save new table data from node-red in vue data items
      
    });

   
  }, // --- End of mounted hook --- //
}); // --- End of app1 --- //

// EOF

Inject a msg from the flow to populate the table data

2 Likes

@UnborN I want to thank you so much for taking the time to build an example that applies directly to my use case. I've spent the last two days going down the rabbit hole trying to figure this out.
Thank you again!

you are welcome Rybitski ..
if you are new to Vue .. may i recommend some excellent video tutorials from the NetNinja on youtube that covers the basics.

Vue JS 2 Tutorial

1 Like

Thanks for the link, I'm on episode 6 now.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.