cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Did you get called away in the middle of writing a post? Don't worry you can find your unfinished post later in the Drafts section of your profile page. X

Widget Development (Iterate infotable)

vxavier
13-Aquamarine

Widget Development (Iterate infotable)

Hello Everyone,

 

I am trying to build a widget, I defined the input parameters in the ide.js file.

 

I defined 'Data' as INFOTABLE, them I defined it's fields as FIELDNAME.

 

Now I am trying to iterate throw the values of my infotable in the runtime.js. How can I do that? 

When I tried to do this: 

var rows = this.getProperty('Data');
for(var i = 0; i < rows.length; i++){

I got: "Exception: Cannot read property 'length' of undefined."

 

This is the right way to get the fields data: "rows[i][this.getProperty('ID')]"??

 

ID is one of the FIELDNAMEs properties defined in the ide.js.

 

1 ACCEPTED SOLUTION

Accepted Solutions

I would recommend that instead of using the mashup logs you instead use the browser's debugger to look at what's wrong. Typically for widget development it's many times more useful because in addition to logging messages you get the ability to actually set up breakpoints and inspect how your code is running. Your custom widget's code (and all other custom widgets you have) will end up into a file called CombinedExtensions.xxxxxx.js which you should find in the debugging sources of your browser's dev tools - then you can just search for your code and debug it.

 

Most likely case is that your updateProperty method never gets called (which is why you don't see any errors in the log). This can happen if you return an unexpected string in renderHtml. It is required that one of the elements you return from renderHtml contain the class widget-content. Though not strictly required, I would also recommend that you return a single root-level element from it, e.g. you could wrap the three elements you are returning with a single <div class="widget-content"> element.

 

You should also keep in mind that the script tag you return in renderHtml will likely not load the script synchronously. There might be a chance that the JSGantt library you are using in afterRender will not have been loaded by the time you try to use it, which may cause the widget to fail to initialize.

View solution in original post

4 REPLIES 4

Hello,

 

Typically, when you work with infotables in widgets, they only get their values from bindings which means they won't be immediately available in afterRender like other static properties. Instead, you should try to get its rows when the value is updated because of the binding. For this you should implement the updateProperty method in your runtime.js and work with the values from there e.g.:

 

this.updateProperty = function (updatePropertyInfo) {

    // updatePropertyInfo is a catch-all method for all bindable properties

    // therefore the first step is to check which property was updated

    if (updatePropertyInfo.TargetProperty == 'Data') {

        // In here the updatePropertyInfo parameter contains the new value

        // Thingworx does not automatically update the property, but it can be set here

        // Note that this the complete infotable, e.g. the data rows are in:

        // this.getProperty('Data').rows and not directly in this.getProperty('Data')

        this.setProperty('Data', updatePropertyInfo.SinglePropertyValue);

 

        // Specifically for infotable values, the updatePropertyInfo parameter contains a field

        // called 'ActualDataRows' that has the infotable rows

        for (var i = 0; i < updatePropertyInfo.ActualDataRows.length; i++) {

            var row = updatePropertyInfo.ActualDataRows[i];

            // ... additional work with the rows can go here

        }

    }

}

vxavier
13-Aquamarine
(To:bmihaiciuc)

Good morning,

 

I tried this way, please tell me if I am doing something wrong. 

TW.Runtime.Widgets.ganttchart= function () {
	this.renderHtml = function () {
		// return any HTML you want rendered for your widget
		// If you want it to change depending on properties that the user
		// has set, you can use this.getProperty(propertyName). In
		// this example, we'll just return static HTML
		return 	'<link rel="stylesheet" type="text/css" href="../Common/extensions/GanttChart/ui/ganttchart/jsgantt.css" />'+
			'<script language="javascript" src="../Common/extensions/GanttChart/ui/ganttchart/jsgantt.js"></script>'+
			'<div style="position:relative" class="gantt" id="GanttChartDIV"></div>';
	};

	this.afterRender = function () {
		// NOTE: this.jqElement is the jquery reference to your html dom element
		// 		 that was returned in renderHtml()

		// get a reference to the value element
		// update that DOM element based on the property value that the user set
		// in the mashup builder

		//Create my GanttChart
		var g = new JSGantt.GanttChart(this.domElementId, this.getProperty('Format'));

		
	};

	// this is called on your widget anytime bound data changes
	this.updateProperty = function (updatePropertyInfo) {

		if (updatePropertyInfo.TargetProperty == 'Data') {

	        // In here the updatePropertyInfo parameter contains the new value

	        // Thingworx does not automatically update the property, but it can be set here

	        // Note that this the complete infotable, e.g. the data rows are in:

	        // this.getProperty('Data').rows and not directly in this.getProperty('Data')

	        this.setProperty('Data', updatePropertyInfo.SinglePropertyValue);
	        // Specifically for infotable values, the updatePropertyInfo parameter contains a field

	        // called 'ActualDataRows' that has the infotable rows

	        for (var i = 0; i < updatePropertyInfo.ActualDataRows.length; i++) {

	            var row = updatePropertyInfo.ActualDataRows[i];

	            // add the rows for the GanttChartt
				g.AddTaskItem(new JSGantt.TaskItem(row[this.getProperty('ID')], row[this.getProperty('Name')], row[this.getProperty('Start')], row[this.getProperty('End')], row[this.getProperty('Class')],'', 0, row[this.getProperty('Resource')], row[this.getProperty('Completion')],  1,row[this.getProperty('Parent')],row[this.getProperty('Open')],'','','',g));
	        }
	        g.Draw();

	    }

	}
};

This is the output from the Show/Hide log in the mashup runtime: 

 

09:59:20 INFO - In-page logger initialized.
09:59:20 INFO - ThingWorx Mashup Runtime vundefined
09:59:20 WARN - trying to set a parameter that is not defined: "forceClose". Ignoring it

I would recommend that instead of using the mashup logs you instead use the browser's debugger to look at what's wrong. Typically for widget development it's many times more useful because in addition to logging messages you get the ability to actually set up breakpoints and inspect how your code is running. Your custom widget's code (and all other custom widgets you have) will end up into a file called CombinedExtensions.xxxxxx.js which you should find in the debugging sources of your browser's dev tools - then you can just search for your code and debug it.

 

Most likely case is that your updateProperty method never gets called (which is why you don't see any errors in the log). This can happen if you return an unexpected string in renderHtml. It is required that one of the elements you return from renderHtml contain the class widget-content. Though not strictly required, I would also recommend that you return a single root-level element from it, e.g. you could wrap the three elements you are returning with a single <div class="widget-content"> element.

 

You should also keep in mind that the script tag you return in renderHtml will likely not load the script synchronously. There might be a chance that the JSGantt library you are using in afterRender will not have been loaded by the time you try to use it, which may cause the widget to fail to initialize.

vxavier
13-Aquamarine
(To:bmihaiciuc)

After a lot of tries, the widget finally came alive. Thank you, your tips really helped me. 

 

Cheers,
Vinícius.

Top Tags