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

Community Tip - Did you know you can set a signature that will be added to all your posts? Set it here! X

Unable to Set Binding Data for Custom Widget - Console Error

WesHuber
10-Marble

Unable to Set Binding Data for Custom Widget - Console Error

Hi everyone,

 

I have been working on a custom widget and everything is working as expected except for the bound data. The property is unable to set bound data, and I am getting an error in the console that might be related.

 

Any help is greatly appreciated. I've scoured the internet and forums for any help on this. I honestly think it is an error with my thingworx environment or dependancies of thingworx at this point...

 

Here is the error I am seeing:
widgetError.PNG

Here is my IDE Code:

 

 

 

 

 

 

 

TW.IDE.Widgets.customgauge = function () {
	console.log("Hi From custom Gauge");
	this.widgetIconUrl = function() {
		return  "'../Common/extensions/TWExtension3/ui/customgauge/default_widget_icon.ide.png'";
	};

	this.widgetProperties = function () {
		return {
			'name': 'BrockSuperGauge',
			'description': 'Cusom Gauge Widget',
			'category': ['Common'],
			'properties': {
				'Value': {
					'baseType': 'NUMBER',
					'defaultValue': 0,
					'isBindingTarget': true
				},
				'Fail Limit': {
					'baseType': 'STRING',
					'defaultValue': '35',
					'isBindingTarget': true
				},
				'Success Limit': {
					'baseType': 'STRING',
					'defaultValue': '75',
					'isBindingTarget': true
				},
				'Label': {
					'baseType': 'STRING',
					'defaultValue': 'Label',
					'isBindingTarget': true
				}
			}
		}
	};

	this.afterSetProperty = function (name, value) {
		console.log("Hi from after set property");
		this.updatedProperties();
		/*var thisWidget = this;
				var refreshHtml = false;
				switch (name) {
		    case 'Style':
		    case 'Value':
		        thisWidget.jqElement.find('.brock-number').text(value);
		        break; // <-- Add this break statement
		    case 'Alignment':
		        refreshHtml = false;
		        break;
		    default:
		        break;
		}
		return refreshHtml; */
	};

	this.renderHtml = function () {
		console.log("Hi from renderHTML");
		// 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).
		//return 	'<div class="widget-content widget-customgauge">' +
			//'<span class="customgauge-property">' + this.getProperty('CustomGauge Property') + '</span>' +
				//'</div>';
		return '<div class="brock-gauge-wrapper">' +
		'<div class="brock-label">'+ this.getProperty('Label') +'</div>' +
		'<div class="brock-gauge" style="--gauge-width: 200px; --min: 0; --max: 100; --actual-value: '+ this.getProperty('Value') +'">' +
    		'<div class="brock-slices">' +
      			'<div class="brock-marker" style="--bg: #e84c3d; --trigg: 0"></div>' +
      			'<div class="brock-marker" style="--bg: #f1970f; --trigg: '+ this.getProperty('Fail Limit') +'"></div>' +
      			'<div class="brock-marker" style="--bg: #1eaa59; --trigg: '+ this.getProperty('Success Limit') +'"></div>' +
    		'</div>' +

    		'<div class="brock-needle"></div>' +

    		'<div class="brock-gauge-center">' +
      			'<div class="brock-number">'+ this.getProperty('Value') +'%</div>' +
    		'</div>' +
  		'</div>' +
	'</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
		//valueElem = this.jqElement.find('.brock-number');
		// update that DOM element based on the property value that the user set
		// in the mashup builder
		//valueElem.text(this.getProperty('Value'));
		//this.jqElement.find('.brock-number').text(this.getProperty('Value'));
		//this.jqElement.find('.brock-label').text(this.getProperty('Label'));

	//};
this.afterRender = function () {
  var thisWidget = this;
console.log("Hi From after Render");
  // Register a binding handler for each bound property
  //TW.Runtime.bind(thisWidget.getProperty('Value'), function(value) {
   // thisWidget.jqElement.find('.brock-number').text(value);
  //});
/*  TW.Runtime.bind(thisWidget.getProperty('Fail Limit'), function(value) {
    thisWidget.jqElement.find('.brock-marker:eq(1)').css('--trigg', value);
  });
  TW.Runtime.bind(thisWidget.getProperty('Success Limit'), function(value) {
    thisWidget.jqElement.find('.brock-marker:eq(2)').css('--trigg', value);
  });
  TW.Runtime.bind(thisWidget.getProperty('Label'), function(value) {
    thisWidget.jqElement.find('.brock-label').text(value);
  });*/

  // Set the initial value of each bound property
  thisWidget.jqElement.find('.brock-number').text(thisWidget.getProperty('Value'));
  thisWidget.jqElement.find('.brock-marker:eq(1)').css('--trigg', thisWidget.getProperty('Fail Limit'));
  thisWidget.jqElement.find('.brock-marker:eq(2)').css('--trigg', thisWidget.getProperty('Success Limit'));
  thisWidget.jqElement.find('.brock-label').text(thisWidget.getProperty('Label'));
};
};

 

 

 

 

 

 

 

And my Runtime Code:

 

 

 

 

 

 

TW.Runtime.Widgets.customgauge= function () {
	  console.log("hi from Custom Gauge");
	this.renderHtml = function () {
		console.log("hi from Render HTML");
		// 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 	'<div class="widget-content widget-customgauge">' +
		//			'<span class="customgauge-property">' + this.getProperty('CustomGauge Property') + '</span>' +
		//		'</div>';
		return '<div class="brock-gauge-wrapper">' +
		'<div class="brock-label">'+ this.getProperty('Label') +'</div>' +
		'<div class="brock-gauge" style="--gauge-width: 200px; --min: 0; --max: 100; --actual-value: '+ this.getProperty('Value') +'">' +
    		'<div class="brock-slices">' +
      			'<div class="brock-marker" style="--bg: #e84c3d; --trigg: 0"></div>' +
      			'<div class="brock-marker" style="--bg: #f1970f; --trigg: '+ this.getProperty('Fail Limit') +'"></div>' +
      			'<div class="brock-marker" style="--bg: #1eaa59; --trigg: '+ this.getProperty('Success Limit') +'"></div>' +
    		'</div>' +

    		'<div class="brock-needle"></div>' +

    		'<div class="brock-gauge-center">' +
      			'<div class="brock-number">'+ this.getProperty('Value') +'%</div>' +
    		'</div>' +
  		'</div>' +
	'</div>';
	};

	this.afterRender = function () {
		console.log('Hi from After Render')
		// NOTE: this.jqElement is the jquery reference to your html dom element
		// 		 that was returned in renderHtml()

		// get a reference to the value element
		valueElem = this.jqElement.find('.brock-number');
		// update that DOM element based on the property value that the user set
		// in the mashup builder
		valueElem.text(this.getProperty('Value'));
		this.jqElement.find('.brock-number').text(this.getProperty('Value'));
		this.jqElement.find('.brock-label').text(this.getProperty('Label'));
	
	};

/*this.afterRender = function () {
  		thisWidget = this;

  // Register a binding handler for each bound property
  /*TW.Runtime.bind(thisWidget.getProperty('Value'), function(value) {
    thisWidget.jqElement.find('.brock-number').text(value);
  });
  TW.Runtime.bind(thisWidget.getProperty('Fail Limit'), function(value) {
    thisWidget.jqElement.find('.brock-marker:eq(1)').css('--trigg', value);
  });
  TW.Runtime.bind(thisWidget.getProperty('Success Limit'), function(value) {
    thisWidget.jqElement.find('.brock-marker:eq(2)').css('--trigg', value);
  });
  TW.Runtime.bind(thisWidget.getProperty('Label'), function(value) {
    thisWidget.jqElement.find('.brock-label').text(value);
  }); */

  /*// Set the initial value of each bound property
  thisWidget.jqElement.find('.brock-number').text(thisWidget.getProperty('Value'));
  thisWidget.jqElement.find('.brock-marker:eq(1)').css('--trigg', thisWidget.getProperty('Fail Limit'));
  thisWidget.jqElement.find('.brock-marker:eq(2)').css('--trigg', thisWidget.getProperty('Success Limit'));
  thisWidget.jqElement.find('.brock-label').text(thisWidget.getProperty('Label'));
  console.log("hi from after render");
}; */


	// this is called on your widget anytime bound data changes
	this.updateProperty = function (updatePropertyInfo) {
		console.log("hi from Update Property");
		// TargetProperty tells you which of your bound properties changed
		if (updatePropertyInfo.TargetProperty === 'Value') {
			valueElem.text(updatePropertyInfo.SinglePropertyValue);
			thisWidget.jqElement.find('.brock-number').text(value);
			this.setProperty('Value', updatePropertyInfo.SinglePropertyValue);
		}
		console.log("updated value ==");
		console.log(thisWidget.getProperty('Value'));
	};
};

 

 

 

 

 

 

 

 

 

 

 

 

 

ACCEPTED SOLUTION

Accepted Solutions

Hi Constantine,

 

Thank you for the reply and for linking that repo that was extremely helpful. I still have not solved my problem, but I think I am closer.

 

The main issue I am facing is the function this.UpdateProperty() is not being called. Any idea why that might be?

 

Also are there any other plugin repositories you recommend I check out?

 

Thanks again for the help!

 

Best regards,

Wes

View solution in original post

4 REPLIES 4

Hello,

 

Just a couple of thoughts:

  1. Looks like you commented out a bit too much, e.g. you use "thisWidget" variable in updateProperty, but you initialize it in the commented out block.
  2. Consider using this.xxx for those "shared" variables, e.g. this.valueElem;
  3. This error suggests something screws up ThingWorx runtime. This is often caused by misbehaving extensions. Therefore, a). Try to remove other extensions or just retry on a virgin ThingWorx installation; b). Double-check that you imported the latest version of your extension; c). Restart ThingWorx, clear your browser cache, and retest in a Private browser tab;
  4. When nothing helps and I'm stuck with my UI extension, I restart from scratch at some point, i.e. take an empty minimal example and import it, ensuring it works. Then start (re)adding your logic into it. Here's my go-to minimalistic example, which handles binding correctly in 9.3.x: https://github.com/vilia-fr/twx-infotable-to-json-ext

Good luck!

 

/ Constantine

 

 

Hi Constantine,

 

Thank you for the reply and for linking that repo that was extremely helpful. I still have not solved my problem, but I think I am closer.

 

The main issue I am facing is the function this.UpdateProperty() is not being called. Any idea why that might be?

 

Also are there any other plugin repositories you recommend I check out?

 

Thanks again for the help!

 

Best regards,

Wes

Hi Constantine, this was useful as I was able to use this repo as a starter template and get the bindings working and compare to what I had to see what I was missing.

For reference I was missing the <div class="widget-content"></div> around my entire widget. Ad 

Update - I still have not found a solution for this. I found another thread with the same issue: https://community.ptc.com/t5/ThingWorx-Developers/Custom-widget-updateProperty-will-not-called/m-p/555833#M29203

 

I am running TW version 9.3 and TW Extension SDK version 9.3

Announcements


Top Tags