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

Community Tip - When posting, your subject should be specific and summarize your question. Here are some additional tips on asking a great question. X

Infotable Source on Widget Development

karnoia
6-Contributor

Infotable Source on Widget Development

Hi everybody,

 

I have been stuck on this for a while. I had developed several widgets before but I had never needed an infotable as output/source. I have found an small example as answer on another topic of this forum, but I can´t seem to make it work. I tried to use the Grid widget that Thingworx has an example, but I am still stuck.

 

On the .ide file, I have the infotable defined as this:

'EditedTable': {
'isBindingSource': true,
'baseType': 'INFOTABLE',
'description': 'Infotable where all the modifications are getting saved'
},

 

And on the .runtime file I have it like this:

var outputTable = TW.InfoTableUtilities.CloneInfoTable({ "dataShape" : { "fieldDefinitions" : infoTableDataShape}, "rows" : item_Data_array });
this.updateProperty('EditedTable',outputTable);

 

I think I am using the correct syntax and that the format of the item_data_array is the right one since I compared it to the infotable that I use as input on the widget (the datashape is directly read from the input one). I have even tried to break the code on the developer mode on Chrome just before setting it, and set this outputTable as the response that I have on the service that send the input infotable.

 

If it is not so clear, I could add some screenshots.

 

Regards,

JNanin

1 ACCEPTED SOLUTION

Accepted Solutions
jamesm1
5-Regular Member
(To:karnoia)

Hey @karnoia,

 

I have done this before in a widget and just took a look at the differences, and the only thing I see is that I am using setProperty instead of updateProperty;

 

First, I have a global variable valled clonedRows that I set when the bound data is refreshed:

 

    this.updateProperty = function (updatePropertyInfo) {
        // TargetProperty tells you which of your bound properties changed
        if (updatePropertyInfo.TargetProperty === 'Data') {
            dataRows = updatePropertyInfo.ActualDataRows;
            clonedRows = TW.InfoTableUtilities.CloneInfoTable({ "dataShape" : { "fieldDefinitions" : updatePropertyInfo.DataShape}, "rows" : updatePropertyInfo.ActualDataRows });

            if(thisWidget.getProperty("IsEditable") === true) {
                thisWidget.setProperty('EditedTable', clonedRows);
            }

            updateWidget();
        } else if (updatePropertyInfo.TargetProperty === 'ErrorIndex') {
            errorRow = parseInt(updatePropertyInfo.SinglePropertyValue);
            console.log('errorRow = ' + errorRow);
            thisWidget.updateErrorRow();
        }
    };

Then, whenever I update the widget I change the corresponding row in the clonedRows table and set the EditedTable property again:

 

    // called whenever we need to redraw the widget
    var updateWidget = function() {
        $('#' + thisWidget.jqElementId + '> .ruleviz-segment').remove();
        if (dataRows && dataRows.length > 0) {
            for (var i = 0; i < dataRows.length; ++i) {
                var row = dataRows[i];

                var html = '';

                if (isEditable && row.Type === 'PROPERTY' ) {
                    html = '<input class="ruleviz-segment ruleviz-segment-' + row.Type + '" placeholder="' + row.RulePart +'">'
                        + '</input>';
                } else { 
                    html = '<div class="ruleviz-segment ruleviz-segment-' + row.Type + '">'
                        + row.RulePart
                        + '</div>';
                }
                thisWidget.jqElement.append(html);
            }
        }

        // If the table is editable then only to selection/on click on the inputs and not the divs.
        if (isEditable) {
            $('#' + thisWidget.jqElementId + '> input.ruleviz-segment').bind('click', segmentOnClick);
            thisWidget.jqElement.find('input').bind('change', function() {
                var index = $(this).index() - 1;
                clonedRows.rows[index].RulePart = $(this).val();
                thisWidget.setProperty('EditedTable',clonedRows);
            });
        } else {
            $('#' + thisWidget.jqElementId + '> .ruleviz-segment').bind('click', segmentOnClick);
        }

Let me know if this helps.

 

Thanks!

 

View solution in original post

8 REPLIES 8
slangley
23-Emerald II
(To:karnoia)

Hi @karnoia.

 

Have you checked the logs for error messages?  That may shed some light on the cause of the problem.

 

Regards.

 

--Sharon

karnoia
6-Contributor
(To:slangley)

Hi @slangley,

 

Thanks for the reply. I had checked them and the console of the navigator too, but I am not getting any errors related to that. If I link the Infotable Source to a service to read the data, I get that the infotable is undefined, like it wasn't properly defined. But since I have even tried with the structure of the input Infotable, I don't know what else to do.

 

Regards,

JNanin

slangley
23-Emerald II
(To:karnoia)

Hi @karnoia.

 

It sounds like you are creating your own widget.  If so, we would need the widget to review and try to recreate the issue.  Are you able to share that?

 

Regards.

 

--Sharon

karnoia
6-Contributor
(To:slangley)

Hi @slangley,

 

I am. And I have done a different one as example of the problem that I am having since the one that I was developing couldn't be shared freely. I used the same structure on both in regards of the input and output infotables; I hope this helps. If needed, I can send a Mashup and Thing with the small example that I was using for testing the widget.

 

Regards,

JNanin

slangley
23-Emerald II
(To:karnoia)

Hi @karnoia.

 

We tried to test with your custom extension, and did see the behavior you were describing.  However, we are not sure exactly what the use case is for this extension.  Can you provide more details around that?  Is there some reason you are not using the out of the box grid?

 

Regards.

 

--Sharon

karnoia
6-Contributor
(To:slangley)

Hi @slangley,

 

This was just an example of the code for generating an infotable on a widget that I was trying to use, and which I thought it was correct. I can't share the widget that I am developing since it uses libraries that you need to pay to use, that is why I used an old widget that I had developed and added the infotable part.

 

Would it be possible to get an example of how to generate an infotable source from inside a widget? That is what I need.

 

Regards,

JNanin

jamesm1
5-Regular Member
(To:karnoia)

Hey @karnoia,

 

I have done this before in a widget and just took a look at the differences, and the only thing I see is that I am using setProperty instead of updateProperty;

 

First, I have a global variable valled clonedRows that I set when the bound data is refreshed:

 

    this.updateProperty = function (updatePropertyInfo) {
        // TargetProperty tells you which of your bound properties changed
        if (updatePropertyInfo.TargetProperty === 'Data') {
            dataRows = updatePropertyInfo.ActualDataRows;
            clonedRows = TW.InfoTableUtilities.CloneInfoTable({ "dataShape" : { "fieldDefinitions" : updatePropertyInfo.DataShape}, "rows" : updatePropertyInfo.ActualDataRows });

            if(thisWidget.getProperty("IsEditable") === true) {
                thisWidget.setProperty('EditedTable', clonedRows);
            }

            updateWidget();
        } else if (updatePropertyInfo.TargetProperty === 'ErrorIndex') {
            errorRow = parseInt(updatePropertyInfo.SinglePropertyValue);
            console.log('errorRow = ' + errorRow);
            thisWidget.updateErrorRow();
        }
    };

Then, whenever I update the widget I change the corresponding row in the clonedRows table and set the EditedTable property again:

 

    // called whenever we need to redraw the widget
    var updateWidget = function() {
        $('#' + thisWidget.jqElementId + '> .ruleviz-segment').remove();
        if (dataRows && dataRows.length > 0) {
            for (var i = 0; i < dataRows.length; ++i) {
                var row = dataRows[i];

                var html = '';

                if (isEditable && row.Type === 'PROPERTY' ) {
                    html = '<input class="ruleviz-segment ruleviz-segment-' + row.Type + '" placeholder="' + row.RulePart +'">'
                        + '</input>';
                } else { 
                    html = '<div class="ruleviz-segment ruleviz-segment-' + row.Type + '">'
                        + row.RulePart
                        + '</div>';
                }
                thisWidget.jqElement.append(html);
            }
        }

        // If the table is editable then only to selection/on click on the inputs and not the divs.
        if (isEditable) {
            $('#' + thisWidget.jqElementId + '> input.ruleviz-segment').bind('click', segmentOnClick);
            thisWidget.jqElement.find('input').bind('change', function() {
                var index = $(this).index() - 1;
                clonedRows.rows[index].RulePart = $(this).val();
                thisWidget.setProperty('EditedTable',clonedRows);
            });
        } else {
            $('#' + thisWidget.jqElementId + '> .ruleviz-segment').bind('click', segmentOnClick);
        }

Let me know if this helps.

 

Thanks!

 

karnoia
6-Contributor
(To:jamesm1)

Hi @jamesm1,

 

You are completely right about the setProperty! I was following an example that I saw on the forum and I didn't even think about it since, in my mind, what I was doing was updating the infotable. Pretty dumb on my part :-/

Thank you very much for the help and have a great day.

 

Regards,

JNanin

 

 

Top Tags