Vuejs binding to tabulator?

hi all
I need updat my tabulator with Uibuilder but I cant
please any ids

 var tabledata = [
 	{id:1, name:"Oli Bob", age:"12", col:"red", dob:""},
 	{id:2, name:"Mary May", age:"1", col:"blue", dob:"14/05/1982"},
 	{id:3, name:"Christine Lobowski", age:"42", col:"green", dob:"22/05/1982"},
 	{id:4, name:"Brendon Philips", age:"125", col:"orange", dob:"01/08/1980"},
 	{id:5, name:"Margret Marmajuke", age:"16", col:"yellow", dob:"31/01/1999"},
 ];

i changed to

var myVar = {
    get a() {
        return app1.TableData
    }
    
}

//define some sample data
var tabledata = myVar.a

but not work
this my demo

[{"id":"ac0f61dd.69e26","type":"tab","label":"Flow 2","disabled":false,"info":""},{"id":"f08129f6.4ada58","type":"comment","z":"ac0f61dd.69e26","name":"uibuilder/jQuery Example","info":"[Front-End](/jq)\n\n## Configuration\n\nInstall jQuery via the nodes configuration panel.\n\nThen update the files:\n\n* `index.html`\n* `index.js`\n* `index.css`\n\nAccording to the jQuery example(s) in the \n[WIKI](https://github.com/TotallyInformation/node-red-contrib-uibuilder/wiki/Example:-JQuery)\nwhich are also included in the 3 other comment nodes in this example.","x":210,"y":80,"wires":[]},{"id":"c30edc95.8f826","type":"comment","z":"ac0f61dd.69e26","name":"index.html","info":"<!doctype html>\n<html lang=\"en\"><head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <meta name=\"viewport\" content=\"width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes\">\n\n    <title>uibuilder jQuery example</title>\n    <meta name=\"description\" content=\"Node-RED uibuilder - Example using jQuery\">\n\n    <link rel=\"icon\" href=\"./images/node-blue.ico\">\n\n    <!-- OPTIONAL: Normalize is used to make things the same across browsers. Index is for your styles -->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"../uibuilder/vendor/normalize.css/normalize.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"./index.css\" media=\"all\">\n\n</head><body>\n    <!-- The \"app\" element is where the code for dynamic updates is attached -->\n    <div id=\"app\">\n        <h1>\n            Welcome to UIbuilder for Node-RED\n        </h1>\n        <p>\n            This is an example of using uibuilder with jQuery. If you open the developer console, you will see some debug output.\n            You can also see some dynamic data updating below, thanks to JQuery.\n            Additional information may be available in the\n            <a href=\"https://github.com/TotallyInformation/node-red-contrib-uibuilder/wiki/Example:-JQuery\">WIKI</a>\n        </p>\n        <p>\n            Please see the README for the\n            <a href=\"https://github.com/TotallyInformation/node-red-contrib-uibuilder\">node-red-contrib-uibuilder</a>\n            node for details on how to use uibuilder.\n        </p>\n        <h2>Dynamic Data (via JQuery)</h2>\n        <p>UIBuilder Front-End Version: <span id=\"feVersion\"></span></p>\n        <p>Websocket State: <span id=\"socketConnectedState\"></span></p>\n        <p>Messages Received: <span id=\"msgsReceived\"></span></p>\n        <p>Control Messages Received: <span id=\"msgsControl\"></span></p>\n        <p>Messages Sent: <span id=\"msgsSent\"></span></p>\n        <p>Last Message Received:</p>\n        <code id=\"showMsg\"></code>\n        <p>Last Control Message Received:</p>\n        <code id=\"showCtrlMsg\"></code>\n        <p>Last Message Sent:</p>\n        <code id=\"showMsgSent\"></code>\n    </div>\n    <!-- These MUST be in the right order. Note no leading / -->\n    <!-- REQUIRED: Socket.IO is loaded only once for all instances\n                     Without this, you don't get a websocket connection -->\n    <script src=\"../uibuilder/vendor/socket.io/socket.io.js\"></script>\n\n    <!-- --- Vendor Libraries - Load in the right order --- -->\n    <script src=\"../uibuilder/vendor/jquery/dist/jquery.min.js\"></script>\n\n    <!-- REQUIRED: Sets up Socket listeners and the msg object -->\n    <!-- <script src=\"./uibuilderfe.js\"></script>   //dev version -->\n    <script src=\"./uibuilderfe.min.js\"></script> <!--    //prod version -->\n    <!-- OPTIONAL: Put your custom code in here -->\n    <script src=\"./index.js\"></script>\n\n</body></html>\n","x":400,"y":80,"wires":[],"icon":"node-red/parser-html.svg"},{"id":"8bd07771.336748","type":"comment","z":"ac0f61dd.69e26","name":"index.js","info":"/* jshint browser: true, esversion: 5, asi: true */\n/*globals $, uibuilder */\n// @ts-nocheck\n/*\n  Copyright (c) 2019 Julian Knight (Totally Information)\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n*/\n'use strict'\n\n/** @see https://github.com/TotallyInformation/node-red-contrib-uibuilder/wiki/Front-End-Library---available-properties-and-methods */\n\n// When JQuery is ready, update\n$( document ).ready(function() {\n    /** **REQUIRED** Start uibuilder comms with Node-RED @since v2.0.0-dev3\n     * Pass the namespace and ioPath variables if hosting page is not in the instance root folder\n     * e.g. If you get continual `uibuilderfe:ioSetup: SOCKET CONNECT ERROR` error messages.\n     * e.g. uibuilder.start('/nr/uib', '/nr/uibuilder/vendor/socket.io') // change to use your paths/names\n     */\n    uibuilder.start()\n\n    // Initial set\n    $('#msgsReceived').text( uibuilder.get('msgsReceived') )\n    $('#msgsControl').text( uibuilder.get('msgsCtrl') )\n    $('#msgsSent').text( uibuilder.get('msgsSent') )\n    $('#socketConnectedState').text( uibuilder.get('ioConnected') )\n    $('#feVersion').text( uibuilder.get('version') )\n\n    // Turn on debugging (default is off)\n    //uibuilder.debug(true)\n\n    // If msg changes - msg is updated when a standard msg is received from Node-RED over Socket.IO\n    // Note that you can also listen for 'msgsReceived' as they are updated at the same time\n    // but newVal relates to the attribute being listened to.\n    uibuilder.onChange('msg', function(newVal){\n        console.info('property msg changed!')\n        console.dir(newVal)\n        $('#showMsg').text(JSON.stringify(newVal))\n        //uibuilder.set('msgCopy', newVal)\n    })\n\n    // You can get attributes manually. Non-existent attributes return 'undefined'\n    //console.dir(uibuilder.get('msg'))\n\n    // You can also set things manually. See the list of attributes top of page.\n    // You can add arbitrary attributes to the object, you cannot overwrite internal attributes\n\n    // Try setting a restricted, internal attribute - see the warning in the browser console\n    uibuilder.set('msg', 'You tried but failed!')\n\n    // Remember that onChange functions don't trigger if you haven't set them\n    // up BEFORE an attribute change.\n    uibuilder.onChange('msgCopy', function(newVal){\n        console.info('msgCopy changed. New value: ', newVal)\n    })\n\n    // Now try setting a new attribute - this will be an empty object because\n    // msg won't yet have been received\n    uibuilder.set('msgCopy', uibuilder.msg)\n    // Hint: Try putting this set into the onChange for 'msg'\n\n    // As noted, we could get the msg here too\n    uibuilder.onChange('msgsReceived', function(newVal){\n        console.info('New msg sent to us from Node-RED over Socket.IO. Total Count: ', newVal)\n        $('#msgsReceived').text(newVal)\n        // uibuilder.msg is a shortcut for uibuilder.get('msg')\n        //$('#showMsg').text(JSON.stringify(uibuilder.msg))\n    })\n\n    // If Socket.IO connects/disconnects\n    uibuilder.onChange('ioConnected', function(newVal){\n        console.info('Socket.IO Connection Status Changed: ', newVal)\n        $('#socketConnectedState').text(newVal)\n    })\n\n    // If a message is sent back to Node-RED\n    uibuilder.onChange('msgsSent', function(newVal){\n        console.info('New msg sent to Node-RED over Socket.IO. Total Count: ', newVal)\n        $('#msgsSent').text(newVal)\n        $('#showMsgSent').text(JSON.stringify(uibuilder.get('sentMsg')))\n    })\n\n    // If we receive a control message from Node-RED\n    uibuilder.onChange('msgsCtrl', function(newVal){\n        console.info('New control msg sent to us from Node-RED over Socket.IO. Total Count: ', newVal)\n        $('#msgsControl').text(newVal)\n        $('#showCtrlMsg').text(JSON.stringify(uibuilder.get('ctrlMsg')))\n    })\n\n    //Manually send a message back to Node-RED after 2 seconds\n    window.setTimeout(function(){\n        console.info('Sending a message back to Node-RED - after 2s delay')\n        uibuilder.send( { 'topic':'uibuilderfe', 'payload':'I am a message sent from the uibuilder front end' } )\n    }, 2000)\n\n}) // --- End of JQuery Ready --- //\n\n// EOF\n","x":530,"y":80,"wires":[],"icon":"font-awesome/fa-code"},{"id":"9b587d6d.a6fb","type":"comment","z":"ac0f61dd.69e26","name":"index.css","info":"body {font-family: sans-serif;}\ndiv, p, code { margin:0.3em; padding: 0.3em;}","x":660,"y":80,"wires":[],"icon":"node-red/hash.svg"},{"id":"d559204.2a02fe","type":"uibuilder","z":"ac0f61dd.69e26","name":"","topic":"","url":"demo","fwdInMessages":false,"allowScripts":false,"allowStyles":false,"copyIndex":true,"showfolder":false,"useSecurity":false,"sessionLength":432000,"tokenAutoExtend":false,"x":460,"y":320,"wires":[["f47d534a.e407f"],["820a7d9c.a3af3"]]},{"id":"fcde0509.fb0bb8","type":"inject","z":"ac0f61dd.69e26","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":320,"wires":[["8f905f04.6c10a"]]},{"id":"8f905f04.6c10a","type":"function","z":"ac0f61dd.69e26","name":"","func":"msg.payload = [\n \t{id:1, name:\"demo\", age:\"12\", col:\"red\", dob:\"\"},\n \t{id:2, name:\"test\", age:\"1\", col:\"blue\", dob:\"14/05/1982\"},\n \t{id:3, name:\"caller\", age:\"42\", col:\"green\", dob:\"22/05/1982\"},\n \t{id:4, name:\"alfa\", age:\"125\", col:\"orange\", dob:\"01/08/1980\"},\n \t{id:5, name:\"beta\", age:\"16\", col:\"yellow\", dob:\"31/01/1999\"},\n ];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":300,"y":320,"wires":[["d559204.2a02fe"]]},{"id":"f47d534a.e407f","type":"debug","z":"ac0f61dd.69e26","name":"jquery-debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":650,"y":300,"wires":[]},{"id":"820a7d9c.a3af3","type":"debug","z":"ac0f61dd.69e26","name":"uib controls","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":650,"y":340,"wires":[]}]

Hi .. you havent shared any index.html and index.js files so its impossible to know whats wrong.

Instead of using Tabulator why dont you use bootstrap-vue tables that are already loaded with uibuilder.
Bootstrap-Vue Tables

Example :

index.html

<!doctype html>
<!-- Note that adding an appcache really speeds things up after the first load
    You need to amend the appcache file to meet your needs.
    Don't forget to change the appcache file if you update ANY
    of the files in it otherwise the old versions will ALWAYS be used.
<html lang="en" manifest="./uibuilder.appcache">
-->
<html lang="en">
<!--
    This is the default, template html for uibuilder.
    It is meant to demonstrate the use of VueJS & bootstrap-vue to dynamically
    update the ui based on incoming/outgoing messages from/to the
    Node-RED server.
-->
<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">

            <h2>Simple Bootstrap-Vue table</h2>
            
            <b-table striped hover :items="items"></b-table>
           
        </b-container>
    </div>

    <!-- Dont forget to use minified versions of libraries for production, non-min versions for development only -->
    <!-- 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 -->
    <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>

    <!-- 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://github.com/TotallyInformation/node-red-contrib-uibuilder/wiki/Front-End-Library---available-properties-and-methods */

// eslint-disable-next-line no-unused-vars
new Vue({
    el: '#app',
    data: { 
        //   { age: 40, first_name: 'Dickerson', last_name: 'Macdonald' },
        //   { age: 21, first_name: 'Larsen', last_name: 'Shaw' },
        //   { age: 89, first_name: 'Geneva', last_name: 'Wilson' },
        //   { age: 38, first_name: 'Jami', last_name: 'Carney' }
        items: []
       
        
    }, // --- End of data --- //
  
    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')

        /** **REQUIRED** Start uibuilder comms with Node-RED @since v2.0.0-dev3
         * Pass the namespace and ioPath variables if hosting page is not in the instance root folder
         * e.g. If you get continual `uibuilderfe:ioSetup: SOCKET CONNECT ERROR` error messages.
         * e.g. uibuilder.start('/uib', '/uibuilder/vendor/socket.io') // change to use your paths/names
         * @param {Object=|string=} namespace Optional. Object containing ref to vueApp, Object containing settings, or String IO Namespace override. changes self.ioNamespace from the default.
         * @param {string=} ioPath Optional. changes self.ioPath from the default
         * @param {Object=} vueApp Optional. Reference to the VueJS instance. Used for Vue extensions.
         */
        uibuilder.start(this) // Single param passing vue app to allow Vue extensions to be used.

        //console.log(this)
    },

    /** 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
        // newVal relates to the attribute being listened to.
        uibuilder.onChange('msg', function(msg){
            console.info('[indexjs:uibuilder.onChange] msg received from Node-RED server:', msg)
            app.items = msg.payload 
           
        })

    } // --- End of mounted hook --- //

}) // --- End of app1 --- //

// EOF
1 Like

am sorry
index.html

<!doctype html>
<!-- Note that adding an appcache really speeds things up after the first load
    You need to amend the appcache file to meet your needs.
    Don't forget to change the appcache file if you update ANY
    of the files in it otherwise the old versions will ALWAYS be used.
<html lang="en" manifest="./uibuilder.appcache">
-->
<html lang="en">
<!--
    This is the default, template html for uibuilder.
    It is meant to demonstrate the use of VueJS & bootstrap-vue to dynamically
    update the ui based on incoming/outgoing messages from/to the
    Node-RED server.
-->
<head>
    <link type="text/css" rel="stylesheet" href="../uibuilder/vendor/tabulator-tables/dist/css/tabulator.min.css" />
<script type="text/javascript" src="../uibuilder/vendor/tabulator-tables/dist/js/tabulator.min.js"></script>

    <!-- Your own CSS -->
    
</head><body>


<div id="example-table"></div>
<div id="app"></div>
<script type="text/javascript">
var myVar = {
    get a() {
        return app1.TableData
    }
    
}

//define some sample data
// var tabledata = myVar.a
 var tabledata = [
 	{id:1, name:"Oli Bob", age:"12", col:"red", dob:""},
 	{id:2, name:"Mary May", age:"1", col:"blue", dob:"14/05/1982"},
 	{id:3, name:"Christine Lobowski", age:"42", col:"green", dob:"22/05/1982"},
 	{id:4, name:"Brendon Philips", age:"125", col:"orange", dob:"01/08/1980"},
 	{id:5, name:"Margret Marmajuke", age:"16", col:"yellow", dob:"31/01/1999"},
 ];
 //create Tabulator on DOM element with id "example-table"
var table = new Tabulator("#example-table", {
 	height:205, // set height of table (in CSS or here), this enables the Virtual DOM and improves render speed dramatically (can be any valid css height value)
 	data:tabledata, //assign data to table
 	layout:"fitColumns", //fit columns to width of table (optional)
 	columns:[ //Define Table Columns
	 	{title:"Name", field:"name", width:150},
	 	{title:"Age", field:"age", hozAlign:"left", formatter:"progress"},
	 	{title:"Favourite Color", field:"col"},
	 	{title:"Date Of Birth", field:"dob", sorter:"date", hozAlign:"center"},
 	],
 	rowClick:function(e, row){ //trigger an alert message when the row is clicked
 		alert("Row " + row.getData().id + " Clicked!!!!");
 	},
});

</script>

 <!-- Dont forget to use minified versions of libraries for production, non-min versions for development only -->
    <!-- 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 --- -->
    <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>

    <!-- 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) 2019 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://github.com/TotallyInformation/node-red-contrib-uibuilder/wiki/Front-End-Library---available-properties-and-methods */

// eslint-disable-next-line no-unused-vars
var app1 = new Vue({
    el: '#app',
    data: {
        startMsg    : 'Vue has started, waiting for messages',
        feVersion   : '',
        counterBtn  : 0,
        inputText   : null,
        inputChkBox : false,
        socketConnectedState : false,
        serverTimeOffset     : '[unknown]',
        imgProps             : { width: 75, height: 75 },
        TableData : '[Nothing]',
        msgRecvd    : '[Nothing]',
        msgsReceived: 0,
        msgCtrl     : '[Nothing]',
        msgsControl : 0,

        msgSent     : '[Nothing]',
        msgsSent    : 0,
        msgCtrlSent : '[Nothing]',
        msgsCtrlSent: 0,

        isLoggedOn  : false,
        userId      : null,
        userPw      : null,
        inputId     : '',
    }, // --- End of data --- //
    computed: {
        hLastRcvd: function() {
            var msgRecvd = this.msgRecvd
            if (typeof msgRecvd === 'string') return 'Last Message Received = ' + msgRecvd
            else return 'Last Message Received = ' + this.syntaxHighlight(msgRecvd)
        },
        hLastSent: function() {
            var msgSent = this.msgSent
            if (typeof msgSent === 'string') return 'Last Message Sent = ' + msgSent
            else return 'Last Message Sent = ' + this.syntaxHighlight(msgSent)
        },
        hLastCtrlRcvd: function() {
            var msgCtrl = this.msgCtrl
            if (typeof msgCtrl === 'string') return 'Last Control Message Received = ' + msgCtrl
            else return 'Last Control Message Received = ' + this.syntaxHighlight(msgCtrl)
        },
        hLastCtrlSent: function() {
            var msgCtrlSent = this.msgCtrlSent
            if (typeof msgCtrlSent === 'string') return 'Last Control Message Sent = ' + msgCtrlSent
            //else return 'Last Message Sent = ' + this.callMethod('syntaxHighlight', [msgCtrlSent])
            else return 'Last Control Message Sent = ' + this.syntaxHighlight(msgCtrlSent)
        },
    }, // --- End of computed --- //
    methods: {
        increment: function(event) {
            console.log('Button Pressed. Event Data: ', event)

            // Increment the count by one
            this.counterBtn = this.counterBtn + 1
            var topic = this.msgRecvd.topic || 'uibuilder/vue'
            uibuilder.send( {
                'topic': topic,
                'payload': {
                    'type': 'counterBtn',
                    'btnCount': this.counterBtn,
                    'message': this.inputText,
                    'inputChkBox': this.inputChkBox
                }
            } )

        }, // --- End of increment --- //

        doLogon: function() {
            uibuilder.logon( {
                'id': this.inputId,
            } )
        }, // --- End of doLogon --- //

        doLogoff: function() {
            uibuilder.logoff()
        }, // --- End of doLogon --- //

        // return formatted HTML version of JSON object
        syntaxHighlight: function(json) {
            json = JSON.stringify(json, undefined, 4)
            json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
            json = json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
                var cls = 'number'
                if (/^"/.test(match)) {
                    if (/:$/.test(match)) {
                        cls = 'key'
                    } else {
                        cls = 'string'
                    }
                } else if (/true|false/.test(match)) {
                    cls = 'boolean'
                } else if (/null/.test(match)) {
                    cls = 'null'
                }
                return '<span class="' + cls + '">' + match + '</span>'
            })
            return json
        }, // --- End of syntaxHighlight --- //
    }, // --- 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')

        /** **REQUIRED** Start uibuilder comms with Node-RED @since v2.0.0-dev3
         * Pass the namespace and ioPath variables if hosting page is not in the instance root folder
         * e.g. If you get continual `uibuilderfe:ioSetup: SOCKET CONNECT ERROR` error messages.
         * e.g. uibuilder.start('/uib', '/uibuilder/vendor/socket.io') // change to use your paths/names
         * @param {Object=|string=} namespace Optional. Object containing ref to vueApp, Object containing settings, or String IO Namespace override. changes self.ioNamespace from the default.
         * @param {string=} ioPath Optional. changes self.ioPath from the default
         * @param {Object=} vueApp Optional. Reference to the VueJS instance. Used for Vue extensions.
         */
        uibuilder.start(this) // Single param passing vue app to allow Vue extensions to be used.

        console.log(this)
    },

    /** 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 vueApp = this  // Reference to `this` in case we need it for more complex functions

        // Example of retrieving data from uibuilder
        vueApp.feVersion = uibuilder.get('version')

        // If msg changes - msg is updated when a standard msg is received from Node-RED over Socket.IO
        // newVal relates to the attribute being listened to.
        uibuilder.onChange('msg', function(msg){
            console.info('[indexjs:uibuilder.onChange] msg received from Node-RED server:', msg)
            vueApp.msgRecvd = msg
            vueApp.msgsReceived = uibuilder.get('msgsReceived')
        })

        //#region ---- Debug info, can be removed for live use ---- //

        /** You can use the following to help trace how messages flow back and forth.
         * You can then amend this processing to suite your requirements.
         */

        // If we receive a control message from Node-RED, we can get the new data here - we pass it to a Vue variable
        uibuilder.onChange('ctrlMsg', function(msg){
            console.info('[indexjs:uibuilder.onChange:ctrlMsg] CONTROL msg received from Node-RED server:', msg)
            vueApp.msgCtrl = msg
            vueApp.msgsControl = uibuilder.get('msgsCtrl')
        })

        /** You probably only need these to help you understand the order of processing
         * If a message is sent back to Node-RED, we can grab a copy here if we want to
         */
        uibuilder.onChange('sentMsg', function(msg){
            console.info('[indexjs:uibuilder.onChange:sentMsg] msg sent to Node-RED server:', msg)
            vueApp.msgSent = msg
            vueApp.msgsSent = uibuilder.get('msgsSent')
        })

        /** If we send a control message to Node-RED, we can get a copy of it here */
        uibuilder.onChange('sentCtrlMsg', function(msg){
            console.info('[indexjs:uibuilder.onChange:sentCtrlMsg] Control message sent to Node-RED server:', msg)
            vueApp.msgCtrlSent = msg
            vueApp.msgsCtrlSent = uibuilder.get('msgsSentCtrl')
        })

        /** If Socket.IO connects/disconnects, we get true/false here */
        uibuilder.onChange('ioConnected', function(connected){
            console.info('[indexjs:uibuilder.onChange:ioConnected] Socket.IO Connection Status Changed to:', connected)
            vueApp.socketConnectedState = connected
        })
        /** If Server Time Offset changes */
        uibuilder.onChange('serverTimeOffset', function(serverTimeOffset){
            console.info('[indexjs:uibuilder.onChange:serverTimeOffset] Offset of time between the browser and the server has changed to:', serverTimeOffset)
            vueApp.serverTimeOffset = serverTimeOffset
        })
        /** consol test */
       uibuilder.onChange('msg', function(msg){
         
        console.log(msg.payload)
            vueApp.TableData = msg.payload
            
        })

        /** If user is logged on/off */
        uibuilder.onChange('isAuthorised', function(isAuthorised){
            console.info('[indexjs:uibuilder.onChange:isAuthorised] isAuthorised changed. User logged on?:', isAuthorised)
            console.log('authData: ', uibuilder.get('authData'))
            console.log('authTokenExpiry: ', uibuilder.get('authTokenExpiry'))
            vueApp.isLoggedOn = isAuthorised
        })

        //#endregion ---- Debug info, can be removed for live use ---- //

    } // --- End of mounted hook --- //

}) // --- End of app1 --- //

// EOF

Why have you put some of your js in the html file?

With Vue, if you want your data to be reactive to changes, it needs to be a Vue data variable.

this script not for vue but for tabulator

From your answer i understand that most propably you havent worked with Vue before :wink:
If you dont need it and still want to use tabulator instead of a fully working example of bootstrap-vue tables then here's an example of it :

index.html (i replaced your tabulator links with the online ones - feel free to uncomment your local files )

<!doctype html>
<!-- Note that adding an appcache really speeds things up after the first load
    You need to amend the appcache file to meet your needs.
    Don't forget to change the appcache file if you update ANY
    of the files in it otherwise the old versions will ALWAYS be used.
<html lang="en" manifest="./uibuilder.appcache">
-->
<html lang="en">
<!--
    This is the default, template html for uibuilder.
    It is meant to demonstrate the use of VueJS & bootstrap-vue to dynamically
    update the ui based on incoming/outgoing messages from/to the
    Node-RED server.
-->
<head>
<!--    <link type="text/css" rel="stylesheet" href="../uibuilder/vendor/tabulator-tables/dist/css/tabulator.min.css" />-->
<!--<script type="text/javascript" src="../uibuilder/vendor/tabulator-tables/dist/js/tabulator.min.js"></script>-->

<link href="https://unpkg.com/tabulator-tables@4.9.3/dist/css/tabulator.min.css" rel="stylesheet">
<script type="text/javascript" src="https://unpkg.com/tabulator-tables@4.9.3/dist/js/tabulator.min.js"></script>

<!-- Your own CSS -->
    
</head>
<body>


<div id="example-table"></div>


 <!-- Dont forget to use minified versions of libraries for production, non-min versions for development only -->
    <!-- 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>
<script src="../uibuilder/vendor/jquery/dist/jquery.min.js"></script>
    <!-- Vendor Libraries - Load in the right order -->
    <!-- <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>-->

    <!-- 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 $, uibuilder */
// @ts-nocheck
/*
  Copyright (c) 2019 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://github.com/TotallyInformation/node-red-contrib-uibuilder/wiki/Front-End-Library---available-properties-and-methods */

// When JQuery is ready, update
$( document ).ready(function() {
    /** **REQUIRED** Start uibuilder comms with Node-RED @since v2.0.0-dev3
     * Pass the namespace and ioPath variables if hosting page is not in the instance root folder
     * e.g. If you get continual `uibuilderfe:ioSetup: SOCKET CONNECT ERROR` error messages.
     * e.g. uibuilder.start('/nr/uib', '/nr/uibuilder/vendor/socket.io') // change to use your paths/names
     */
    uibuilder.start()
    
    
//     var myVar = {
//     get a() {
//         return app1.TableData
//     }
    
// }

//define some sample data
// var tabledata = myVar.a
 var tabledata = [
 	{id:1, name:"Oli Bob", age:"12", col:"red", dob:""},
 	{id:2, name:"Mary May", age:"1", col:"blue", dob:"14/05/1982"},
 	{id:3, name:"Christine Lobowski", age:"42", col:"green", dob:"22/05/1982"},
 	{id:4, name:"Brendon Philips", age:"125", col:"orange", dob:"01/08/1980"},
 	{id:5, name:"Margret Marmajuke", age:"16", col:"yellow", dob:"31/01/1999"},
 ];
 //create Tabulator on DOM element with id "example-table"
var table = new Tabulator("#example-table", {
 	height:205, // set height of table (in CSS or here), this enables the Virtual DOM and improves render speed dramatically (can be any valid css height value)
 	data:tabledata, //assign data to table
 	layout:"fitColumns", //fit columns to width of table (optional)
 	columns:[ //Define Table Columns
	 	{title:"Name", field:"name", width:150},
	 	{title:"Age", field:"age", hozAlign:"left", formatter:"progress"},
	 	{title:"Favourite Color", field:"col"},
	 	{title:"Date Of Birth", field:"dob", sorter:"date", hozAlign:"center"},
 	],
 	rowClick:function(e, row){ //trigger an alert message when the row is clicked
 		alert("Row " + row.getData().id + " Clicked!!!!");
 	},
});
    
    
    // Turn on debugging (default is off)
    //uibuilder.debug(true)

    // If msg changes - msg is updated when a standard msg is received from Node-RED over Socket.IO
    // Note that you can also listen for 'msgsReceived' as they are updated at the same time
    // but newVal relates to the attribute being listened to.
    uibuilder.onChange('msg', function(newVal){
        console.info('property msg changed!')
        console.dir(newVal)
        
        tabledata = newVal.payload   // assign new data received to tabledata
        
        table.setData(tabledata)
        .then(function(){
          //run code after table has been successfuly updated
         table.redraw();  // full redraw of table
        })
        .catch(function(error){
         //handle error loading data
        });
        
        
       
        //uibuilder.set('msgCopy', newVal)
    })


    // Remember that onChange functions don't trigger if you haven't set them
    // up BEFORE an attribute change.
    uibuilder.onChange('msgCopy', function(newVal){
        console.info('msgCopy changed. New value: ', newVal)
    })

    // Now try setting a new attribute - this will be an empty object because
    // msg won't yet have been received
    uibuilder.set('msgCopy', uibuilder.msg)
    // Hint: Try putting this set into the onChange for 'msg'

    // As noted, we could get the msg here too
    uibuilder.onChange('msgsReceived', function(newVal){
        console.info('New msg sent to us from Node-RED over Socket.IO. Total Count: ', newVal)
        $('#msgsReceived').text(newVal)
        // uibuilder.msg is a shortcut for uibuilder.get('msg')
        //$('#showMsg').text(JSON.stringify(uibuilder.msg))
    })

    // If Socket.IO connects/disconnects
    uibuilder.onChange('ioConnected', function(newVal){
        console.info('Socket.IO Connection Status Changed: ', newVal)
        $('#socketConnectedState').text(newVal)
    })

    // If a message is sent back to Node-RED
    uibuilder.onChange('msgsSent', function(newVal){
        console.info('New msg sent to Node-RED over Socket.IO. Total Count: ', newVal)
        $('#msgsSent').text(newVal)
        $('#showMsgSent').text(JSON.stringify(uibuilder.get('sentMsg')))
    })

    // If we receive a control message from Node-RED
    uibuilder.onChange('msgsCtrl', function(newVal){
        console.info('New control msg sent to us from Node-RED over Socket.IO. Total Count: ', newVal)
        $('#msgsControl').text(newVal)
        $('#showCtrlMsg').text(JSON.stringify(uibuilder.get('ctrlMsg')))
    })

    //Manually send a message back to Node-RED after 2 seconds
    window.setTimeout(function(){
        console.info('Sending a message back to Node-RED - after 2s delay')
        uibuilder.send( { 'topic':'uibuilderfe', 'payload':'I am a message sent from the uibuilder front end' } )
    }, 2000)

}) // --- End of JQuery Ready --- //

// EOF

send new payload of data to see the data update ( for test .. random age)

msg.payload = [
 	{id:1, name:"demo", age:Math.random()*30, col:"red", dob:""},
 	{id:2, name:"test", age:Math.random()*20, col:"blue", dob:"14/05/1982"},
 	{id:3, name:"caller", age:Math.random()*40, col:"green", dob:"22/05/1982"},
 	{id:4, name:"alfa", age:Math.random()*30, col:"orange", dob:"01/08/1980"},
 	{id:5, name:"beta", age:Math.random()*10, col:"yellow", dob:"31/01/1999"},
 ];
return msg;
1 Like

Thanks Its worked
but you are use jquery lib not vueJs
how update table with vueJs or not possible that

Im glad it worked .. the important thing is to understand how and why it worked at every step of the code :wink:

actually jquery wasnt really needed either .. but i included the library in case you wanted to play around with it instead of Vue because you didnt tell us whether you know Vue.

The nice thing about uibuilder is that it doesnt lock you into using any specific front end library.
You can use jquery, Vue, Angular, React .. even plain Javascript.

If you are indeed interested in Vue i would recommend some excellent video tutorials from theNetNinja

and then you can use Vue-tabulator instead

1 Like

As Colin Andy (sorry Andy) says, I don't think you quite understand what Vue is and how it interacts with other tools.

Vue provides a framework for manipulating the DOM (the visible part of your web ui). It contains a set of features that will automatically update the DOM when data changes. But to make use of that, your data has to be inside the Vue app. It doesn't matter that you feed it to another library.

You are ignoring Vue and using Tabulator independently which means that you have to handle the data yourself. So you probably just need to blank out the data before putting the new data in place.

Also as Colin says, bootstrap-vue which is included in the default template already has a table feature that you can use so unless you really need some feature from Tabulator, you would probably be better off using bootstrap-vue's <b-table> component. It is responsive (adapts to mobile browsers) and also dynamic (reacts to data changes).

You should note that adding vue-tabulator and tabulator adds over 100kb to your page size. Also, the default CSS they provide doesn't match the default bootstrap styling.

However, it does work and I've done a quick trial. If you want to use tabulator locally rather than having to rely on the Internet, use uibuilder's library manager to install BOTH vue-tabulator and tabulator-tables. In your HTML, use the following:

...
    <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.min.css" />
    <link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue-icons.min.css" />

    <link type="text/css" rel="stylesheet" href="../uibuilder/vendor/tabulator-tables/dist/css/tabulator.min.css" />

    <link type="text/css" rel="stylesheet" href="./index.css" media="all">
</head><body>

...

<!-- show tbl using vue tabulator. Use UPDATE strategy if editing is enabled -->
<Vue-Tabulator v-model="roomdata" :options="vtoptions" :integration="{ updateStrategy: 'UPDATE' }" />

...

    <script src="../uibuilder/vendor/socket.io/socket.io.js"></script>
    <script src="../uibuilder/vendor/vue/dist/vue.js"></script>
    <script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.js"></script>
    <script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue-icons.min.js"></script>

    <script src="../uibuilder/vendor/tabulator-tables/dist/js/tabulator.min.js"></script>
    <script src="../uibuilder/vendor/vue-tabulator/dist/vue-tabulator.umd.min.js"></script>

    <script src="./uibuilderfe.min.js"></script>
    <script src="./index.js"></script>
</body></html>

Then in your index.js file:

...

new Vue({
    el: '#app',
    
    data: {

        // Vue-Tabulator/tabulator-tables
        roomdata: [
            {id:1, name:"Oli Bob", age:"12", col:"red", dob:""},
            {id:2, name:"Mary May", age:"1", col:"blue", dob:"14/05/1982"},
            {id:3, name:"Christine Lobowski", age:"42", col:"green", dob:"22/05/1982"},
            {id:4, name:"Brendon Philips", age:"125", col:"orange", dob:"01/08/1980"},
            {id:5, name:"Margret Marmajuke", age:"16", col:"yellow", dob:"31/01/1999"},
        ],
        vtoptions: {
            height:205, // set height of table (in CSS or here), this enables the Virtual DOM and improves render speed dramatically (can be any valid css height value)
            //data:tabledata, //assign data to table
            layout:"fitColumns", //fit columns to width of table (optional)
            columns:[ //Define Table Columns
                {title:"Name", field:"name", width:150},
                {title:"Age", field:"age", align:"left", formatter:"progress"},
                {title:"Favourite Color", field:"col"},
                {title:"Date Of Birth", field:"dob", sorter:"date", align:"center"},
            ],
            rowClick:function(e, row){ //trigger an alert message when the row is clicked
                alert("Row " + row.getData().id + " Clicked!!!!");
            },
        },

...

That gives just static data of course (example data from the Tabulator website). If you update the roomdata array from your uibuilder.onchange function, the table should update. If you don't want to be able to edit the table from your ui, you should remove the integration attribute from the html.


Honestly, I've had a quick play with Tabulator and I can't see any real advantages over b-table. I'd also say that b-table seems faster to render. However, Tabulator does have a few more built-in features like sparklines. I had hoped that editing would be simpler in Tabulator but it really isn't.

I have yet to come across a Vue table component that does editing as easily as some of the jQuery tables. If anyone knows of one, please let me know.

3 Likes

thanks to all
this officiel tabulator link to how use is with vue
Vue Setup
so possibile to use it with uibuilder + vuejs or not ?

As it says in the docs "As a self contained JavaScript library Tabulator should work in just about any web environment you choose to use it in." - So you can certainly use it with uibuilder with or without VueJS. The code I gave before shows it being used with uibuilder and VueJS.

Are you talking about in field editing, or just ease of composition?

If the former I followed a vue example that has a button in each row that allows in-field editing but this could easily be adapted. (Not sure if it would class as easy but it can't be TOO difficult if I can follow it :grin:)