Search code examples
jqueryjsrenderjsviewsdata-linking

JSViews template not updating when the underlying data changes


I'm having an issue with a JSViews template updating when the underlying data changes. It involves a span that is data-linked using a converter function to the underlying data. When the underlying data changes after an async call back to the server, the span text is not updating.

Markup:

{^{for thedata.myarrayobject}}
    <span data-link="{myconverter:var1:} name{:'theName' + var2}"></span>
{{/for}}

Script:

$.views.converters({
    myconverter: function (val) {
        switch (val) {
            case 1: 
                return 'Test1'; 
                break;
            case 2: 
                return 'Test2';
                break;
            default: 
                return 'Default';
        }
    }
});

The span correctly displays on page load based on the values in thedata.myarrayobject. E.g. if we have:

thedata.myarrayobject[0].var1='1';
thedata.myarrayobject[0].var2='John';
thedata.myarrayobject[1].var1='2';
thedata.myarrayobject[1].var2='Matthew';

it will load as:

<span name="theNameJohn">Test1</span>
<span name="theNameMatthew">Test2</span>

However, if the underlying data changes after an async callback to:

thedata.myarrayobject[0].var1='2';
thedata.myarrayobject[0].var2='John';
thedata.myarrayobject[1].var1='1';
thedata.myarrayobject[1].var2='Matthew';

the span text is just staying the same.

I have debugged the js code and the underlying array parameter 'var1' is definitely being set to the new value. I have tried calling:

$.observable(thedata.myarrayobject).refresh(thedata.myarrayobject);

but to no avail.

I obviously want the span text to adjust as the underlying data changes - any help would be greatly appreciated!


Solution

  • In fact to make an update, you need to choose your own strategy for merging the new data (e.g. from an Ajax call) with the previous data.

    But any merge must be done using the 'observable' APIs - so that JsViews receives the data-linking update notifications and updates your UI.

    So depending on your data and scenario, you could use any of the following kinds of update:

    1. Change the leaf values one at a time:

      $.observable(thedata.myarrayobject[0]).setProperty("var1", "2");

    2. Change the leaf values one object at a time:

      $.observable(thedata.myarrayobject[0]).setProperty(newarrayobject[0]);

      (This will pick up any modified properties)

    3. Refresh the whole array with the new objects:

      $.observable(thedata.myarrayobject).refresh(newarrayobject);

      (This will copy the new objects/items over into the myarrayobject)

    4. Update the myarrayobject with the new one:

      $.observable(thedata).setProperty("myarrayobject", newarrayobject);

      So here you are replacing the array with a new one...

    Any or each of the above will trigger updates with the new data values.

    Note that the above methods assume you have downloaded a new data array, newarrayobject which contains updated data to merge into your previous myarrayobject. You don't need to clone either the newarrayobject or the previous myarrayobject.