Strange behaviour on iOS RadListView when page binding context is not re-initialized on every page navigating event

8 posts, 0 answers
  1. Marc
    Marc avatar
    101 posts
    Member since:
    Oct 2013

    Posted 11 Dec 2017 Link to this post

    Hello,

    in some of our pages in the NativeScript app we load data from the server and load it into a RadListView.

     

    Usually we define our Observable (the bindingContext of the page) like this:

    exports.vmList = observableModule.fromObject({
        loading: false,
        countries: new observableArrayModule.ObservableArray(),
     
        loadCountries: function () {
            var self = this;
            self.set("loading", true);
     
            httpModule.request({ url: "https://restcountries.eu/rest/v2/all", method: "GET" }).then(function(response) {
                //clear array and fill with new data
                self.get("countries").splice(0, self.get("countries").length);
                self.get("countries").push(response.content.toJSON());
     
                self.set("loading", false);
            }, function (e) {
                console.log(e);
                self.set("loading", false);
            });
        }
    });

     

    and we set it on navigating event of the page:

    exports.onNavigatingTo = function (args) {
        page = args.object;
        page.bindingContext = vmModule.vmList;
     
        vmModule.vmList.loadCountries();
    };

     

    Here is the problem:

    When navigating to the page for the first time, everything is working as expected. But when calling the page for a second/third/... time, there is some mismatching on the list items layout, as some of the list items are indended. When scrolling down and up, the position of the indended items changes, so it affects some other list items. You can have a look at the provided GIF animation to better understand what is happening on iOS.

    It might be related on what the list item's layout looks like, because we structure it like this:

    <StackLayout className="listitem-outer">
        <StackLayout className="listitem">
             <Label text="{{ name }}" fontSize="12" fontWeight="bold"/>
             <!-- ... -->
        </StackLayout>
    </StackLayout>

    We noticed, that the issue does not occur when we delete the outer StackLayout. But we need this to give the list item a padding, so that it looks like a CardLayout.

     

    Something else that we have noticed is, that the issue does not occur when we make the page bindingContext a class that inherits from the Observable class...

    class VM extends observableModule.Observable {
        constructor() {
            super();
            this.loading = false;
            this.countries = new observableArrayModule.ObservableArray()
        }
     
        loadCountries() {
            //...
        }
    }
    exports.VM = VM;

     

    ... which is initialized everytime we navigate to the page...

    exports.onNavigatingTo = function (args) {
        page = args.object;
        page.bindingContext = new vmModule.VM();
     
        page.bindingContext.loadCountries();
    };

    ... as we have seen this in some NativeScript tutorials.

    We created some sample projects with the issue here

     

    We could set the data binding this way on all pages to overcome the described RadListView issue here, but we are just not sure if this is really best practice to create new instances of the ViewModel on every page navigation, as our previous method is re-using the existing object.

     

    So is this issue related to a bug in the iOS RadListView definition or is the way we are setting the data binding right now just bad practice?

     

    Thank you in advance for any feedback or recommendation and best regards

     

     

  2. Marc
    Marc avatar
    101 posts
    Member since:
    Oct 2013

    Posted 11 Dec 2017 in reply to Marc Link to this post

    What I forgot to mention is our testing environment:

    • NativeScript 3.3.1
    • tns-ios 3.3.0
    • iOS 10 simulator and iPhone 6 with iOS 10.3.1
  3. nikolay.tsonev
    Admin
    nikolay.tsonev avatar
    329 posts

    Posted 12 Dec 2017 Link to this post

    Hello Marc,

    I reviewed your case and found that in your case the while using nested StackLayouts and the data is loaded async via HTTP request, the padding for the child could not be applied every time properly. This happens because the StackLayout needs to know the width of the content while setting up the stylings.This seems to be expected behavior and there is nothing to do with RadListView component.

    Regarding that, to resolve this case you could set up 100 % width for the parent StackLayout or use GridLayout.
    Option 1:
    .listitem {
        background-color: #FCFCF6;
        min-height: 40;
        width:100%;
        padding: 8 10 8 10;
    }

    Option 2:

    <lv:RadListView.itemTemplate>
                    <GridLayout rows="*" columns="*" className="listitem-outer">
                        <StackLayout className="listitem">
                            <Label text="{{ name }}" fontSize="12" fontWeight="bold"/>
                            <Label text="{{ capital }}" fontSize="10"/>
                            <Label text="{{ region }}" fontSize="10"/>
                            <Label text="{{ subregion }}" fontSize="10"/>
                            <Label text="{{ demonym }}" fontSize="10"/>
                            <Label text="{{ population }}" fontSize="10"/>
                        </StackLayout>
                    </StackLayout>
                </lv:RadListView.itemTemplate>

    Let me know if the suggestions resolve the problem or if I could assist you further.

    Regards,
    nikolay.tsonev
    Progress Telerik
    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.
  4. Marc
    Marc avatar
    101 posts
    Member since:
    Oct 2013

    Posted 12 Dec 2017 in reply to nikolay.tsonev Link to this post

    Hello Nikolay,

    thanks for your help. Indeed, using a GridLayout with columns="*" or StackLayout with 100% width solves the issue. So we will definetely revork our listitem templates.

    But I am still wondering why the issue does not occur, when the binding is set with a new instance of the VM class during navigatingTo event of the page: page.bindingContext = new vmModule.VM();

    Do you think this is generally the recommended way to initialize the DataBinding for a page in NativeScript?

     

    We are a little bit concerned that this will create more work for the Garbage Collectors, because usually one should re-use existing objects instead creating new instances of a class, where it is not necessary.

     

    Best regards and thank you in advance

  5. nikolay.tsonev
    Admin
    nikolay.tsonev avatar
    329 posts

    Posted 12 Dec 2017 Link to this post

    Hello Marc,
    We will need some time to research further the case and to find what could cause this behavior. 
    At first glance, both cases (setting up the bindingContext via the fromObject method and while extending Observable) should work in the same way.
    However, we will research the case and will write you back by the end of the week.

    Let me know if this is applicable to you?
    Regards,
    nikolay.tsonev
    Progress Telerik
    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.
  6. Marc
    Marc avatar
    101 posts
    Member since:
    Oct 2013

    Posted 12 Dec 2017 in reply to nikolay.tsonev Link to this post

    Hello Nikolay,

    thank you for your response and for your deeper research.

    That is absolutely applicable.

  7. nikolay.tsonev
    Admin
    nikolay.tsonev avatar
    329 posts

    Posted 13 Dec 2017 Link to this post

    Hello Marc,

    We reviewed the case and found that this problem with the binding context is related to the RadListView. In some cases, the component will not measure the width of its items correctly, which will lead to this strange behavior.

    For your convenience, I logged this problem in our feedback repository. For further info, please keep track on the issue.

    Regards,
    nikolay.tsonev
    Progress Telerik
    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.
  8. Marc
    Marc avatar
    101 posts
    Member since:
    Oct 2013

    Posted 13 Dec 2017 in reply to nikolay.tsonev Link to this post

    Hello Nikolay,

    thank you for your fast feedback and for creating an official issue for this on Github.
    We will track this for further info.

     

    Best regards,
    Marc

Back to Top