NativeScript: DataBinding issue since NativeScript 3.0

Thread is closed for posting
5 posts, 0 answers
  1. Marc
    Marc avatar
    101 posts
    Member since:
    Oct 2013

    Posted 15 May 2017 Link to this post

    Hello,

    as the title already reveals, I have some troubles with dataBinding in our app, since we are starting to upgrade to NativeScript 3.0.

    We have one page on our app, where we dynamically create a TabView with a variable count of TabItems based on the JSON response of the server. Each TabItem contains a ListView with different data items.

    While everything went perfect until using NS 2.5, the binding between an ObservableArray and the ListView (in the current tab of the TabView) does not work anymore and I don't know why.

    While building the TabView, I iterate through the root-list, add one TabItem to the TabView and I create a new ObservableArray like this for each TabItem, that contains the sub-data and this should be visualized by a ListView. I define the ObservableArray like this:

    vmModule.vmCategoriesRoot.set("categoriesSub" + index, new observableArrayModule.ObservableArray([]));

    where vmCategoriesRoot is my Observable for the Page and index contains the selectedTabIndex of the TabView.

    The code above works with NativeScript 2.5, but not with 3.0 and I don't know why. When trying to get the ObservableArray using vmModule.vmCategoriesRoot.get("categoriesSub" + index), it just says it is undefined. I noticed that I could use the following workaround:

    vmModule.vmCategoriesRoot["categoriesSub" + index] = new observableArrayModule.ObservableArray([]);

    This works, but I always used to access the components in my Observable via get and set and I do not know why I need to change the way of accessing a field in my Observable here to get this to work here.

     

    I have created a sample project here, which should help you to reproduce this behaviour. You only need to switch between tns-core-modules 2.5.2 and 3.0 to see the difference.

     

    Best regards and thank you in advance,

    Marc

     

  2. Nikolay Iliev
    Admin
    Nikolay Iliev avatar
    351 posts

    Posted 16 May 2017 Link to this post

    Hello Marc,

    The reason for this to behave differently in 2.5.x and 3.0.0 is a breaking change regarding the Observable constructor. In NativeScript 2.5.x it was possible to pass an object literal to the constructor and this way create an Observable model. With NativeScript 3.x.x this constructor is no longer supported and now we have exposed methods called fromObject and fromObjectRecursive in the observable module. These methods will accept object literal as an argument and will return observable.
    Based on your sample application all that needs to be changed is the way you are creating exported observable vmCountries

    exports.vmCountries = observableModule.fromObject({
        statusWorking: false,
        selectingItems: false,
        selectedTabIndex: 0,
     
        countries1: new observableArrayModule.ObservableArray(),
        countries2: new observableArrayModule.ObservableArray(),
     
        loadCountries: function() {
            console.log("loadCountries")
            var self = this;
            self.set("statusWorking", true);
            self.set("countries1", new observableArrayModule.ObservableArray());
            self.set("countries2", new observableArrayModule.ObservableArray());
     
            httpModule.request({
                url: "http://services.groupkt.com/country/get/all",
                method: "GET",
                headers: {
                    "Content-Type": "application/x-www-form-urlencoded"
                }
            }).then(function (response) {
                var list = response.content.toJSON().RestResponse.result;
     
                list.forEach(function(country){
                    self.get('countries1').push(country);
                    self.get('countries2').push(country);
                });
     
                self.set("statusWorking", false);
            }, function(e) {
                console.log(e);
                self.set("statusWorking", false);
            });
        }
    });
    Note that there is no need to pass an empty array to create new ObservableArray
    e.g.
    countries1: new observableArrayModule.ObservableArray() // no need to pass [] in the constructor

    With this change now you will have access to your Observable model properties and methods and they won't be undefined.

    Regards,
    Nikolay Iliev
    Telerik by Progress
    Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
  3. Marc
    Marc avatar
    101 posts
    Member since:
    Oct 2013

    Posted 16 May 2017 in reply to Nikolay Iliev Link to this post

    Hello Nikolay,

    I need to apologize, the provided link leads to an old test project and not to the project, where I wanted to show you the issue described above.

    The correct project can be found here

    Could you please have another look at this? In this project, I already payed attention to the breaking changes for the Observable constructor and I used the fromObject method according to the documentations.

     

    Thank you in advance and - once again - please excuse me for providing the wrong project.

    Best regards,

    Marc

  4. Nikolay Iliev
    Admin
    Nikolay Iliev avatar
    351 posts

    Posted 16 May 2017 Link to this post

    Hey Marc,

    No problem at all and thank you for the new project link - now I was able to find and diagnose the issue you are describing.

    It appears that the issue you were struggling with is indeed a bug introduced with NativeScript 3.0.0.
    What is happening is that the source code for fromObject is mapping the values that have to be set.
    However, the getter works directly with the passed argument instead of also mapping the values.
    I have logged this as a critical bug here, and the fix will be included in our next version (or probably patch version of tns-core-modules). The release date for the fix will be updated in the logged issue.

    Meanwhile, as a temporary workaround, you can patch the tns-core-modules in your project.
    To do that follow the steps above:
    - remove node_modules and platforms
    - execute npm install
    - go to node_modules/tns-core-modules/data/observable/observable.js
    - change this code (with tns-core-modules@3.0.0 is on line 30)
    Observable.prototype.get = function (name) {
        return this[name];
    };
    To this one
    Observable.prototype.get = function (name) {
        return this._map[name];
    };

    After these changes are made, you can execute your project, and the Observable will work as expected.
    Keep in mind that this is an only temporary solution and each time you remove node_modules the fix will be lost and have to be re-applied again after npm install.

    I am adding 2000 Telerik points for discovering this bug and please accept our apologies for any inconvenience caused!

    Regards,
    Nikolay Iliev
    Telerik by Progress
    Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
  5. Marc
    Marc avatar
    101 posts
    Member since:
    Oct 2013

    Posted 16 May 2017 in reply to Nikolay Iliev Link to this post

    Hi Nikolay,

    I'm glad to hear that this will be fixed soon. I'm looking forward for the patch and I'm going to use your suggested workaround in meantime.

    And thank you for adding the Telerik points!

     

    Best regards,

    Marc

Back to Top