strange behaviour with selecting/unselecting switches within ListView on iOS

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

    Posted 28 Mar 2017 Link to this post

    Hello,

    we have a page in our NativeScript app that allows the user to check or uncheck some items via Switch components within a ListView and the user should be able to select all or unselect all items in the ListView, so that the corresponding switches will be checked or unchecked.

    Unfortunately we notice that the 'isChecked' property of each list item is set correctly, but the state of the Switch is not updated in the UI, unless the user scrolls the 'wrong set' item out of the ListView. Here is a link to a GIF to better understand this description.

    Here is what I am doing:

    <GridLayout rows="auto,auto,*">
        <Button row="0" text="Select all items" tap="selectAllSwitchItems" />
        <Button row="1" text="Unselect all items" tap="unselectAllSwitchItems" />
            <lv:RadListView
                row="2"
                id="myListView"
                items="{{ myItems }}">
             <lv:RadListView.listViewLayout>
                 <lv:ListViewLinearLayout scrollDirection="Vertical" />
             </lv:RadListView.listViewLayout>
             <lv:RadListView.itemTemplate>
                 <GridLayout columns="*, auto" rows="auto">
                    <Label text="{{ label }}" col="0" />
                    <Switch col="1" checked="{{ isChecked }}"/>
                </GridLayout>
            </lv:RadListView.itemTemplate>
        </lv:RadListView>
    </GridLayout>

     

    exports.vmConfig = new observableModule.Observable({
       myItems: new observableArrayModule.ObservableArray([
            { label: "Test", isChecked: true },
            { label: "Test", isChecked: false },
            { label: "Test", isChecked: true },
            { label: "Test", isChecked: true },
            { label: "Test", isChecked: false },
            //...
        ])
    });

     

    exports.selectAllSwitchItems = function() {
        var list = vmModule.vmConfig.get("myItems");
        for(var i = 0; i < list.length; i++) {
            list.getItem(i).isChecked = true;
        }
     
        myListView.refresh();
    };
     
     
    exports.unselectAllSwitchItems = function() {
        var list = vmModule.vmConfig.get("myItems");
        for(var i = 0; i < list.length; i++) {
            list.getItem(i).isChecked = false;
        }
     
        myListView.refresh();
    };

     

    The issue occurs only on iOS, on Android this functionality works fine.

    My testing environment:

    • NativeScript 2.5
    • iPhone 4S (iOS 8.4)

    Does anybody know what is causing this issue? I am thankful for any advice.

     

    Best regards

  2. Answer
    Nikolay Tsonev
    Admin
    Nikolay Tsonev avatar
    340 posts

    Posted 29 Mar 2017 Link to this post

    Hi,
    Thank you for your interest in NativeScript.
    We tested your case and was able to reproduce the behavior you are facing with.
    To be able to change the state of the Switch components inside the RadListView, you should setup isCheckrd property to be an Observable, which contains the boolean value. 
    For example:
    XML

    <Page xmlns="http://schemas.nativescript.org/tns.xsd" xmlns:lv="nativescript-telerik-ui/listview" navigatingTo="navigatingTo" class="page">
     
        <Page.actionBar>
            <ActionBar title="My App" icon="" class="action-bar">
            </ActionBar>
        </Page.actionBar>
     
        <GridLayout rows="auto,auto,*">
        <Button row="0" text="Select all items" tap="selectAllSwitchItems" />
        <Button row="1" text="Unselect all items" tap="unselectAllSwitchItems" />
            <lv:RadListView
                row="2"
                id="myListView"
                items="{{ myItems }}">
             <lv:RadListView.listViewLayout>
                 <lv:ListViewLinearLayout scrollDirection="Vertical" />
             </lv:RadListView.listViewLayout>
             <lv:RadListView.itemTemplate>
                 <GridLayout columns="*, auto" rows="auto">
                    <Label text="{{ label }}" col="0" />
                    <Switch col="1" checked="{{ isChecked.value }}"/>
                </GridLayout>
            </lv:RadListView.itemTemplate>
        </lv:RadListView>
    </GridLayout>
    </Page>


    TypeScript
    import { EventData, Observable } from 'data/observable';
    import { Page } from 'ui/page';
    import { HelloWorldModel } from './main-view-model';
    import {ObservableArray} from "data/observable-array";
    import {RadListView} from "nativescript-telerik-ui/listview"
     
    // Event handler for Page "navigatingTo" event attached in main-page.xml
    var vmConfig;
    var page:Page;
    export function navigatingTo(args: EventData) {
       vmConfig = new Observable({
       myItems: new ObservableArray([
            { label: "Test", isChecked: new Observable({value:true}) },
            { label: "Test", isChecked: new Observable({value:false}) },
            { label: "Test", isChecked: new Observable({value:true}) },
            { label: "Test", isChecked: new Observable({value:true}) },
            { label: "Test", isChecked: new Observable({value:false}) },
        ])
    });
      
        page = <Page>args.object;
     
        page.bindingContext = vmConfig;
    }
     
    export function selectAllSwitchItems(){
        var list = vmConfig.get("myItems");
        for(var i = 0; i < list.length; i++) {
            list.getItem(i).isChecked.set("value", true);
        }
        var listview:RadListView =<RadListView> page.getViewById("myListView");
        listview.refresh();
    }
     
    export function unselectAllSwitchItems(){
        var list = vmConfig.get("myItems");
        for(var i = 0; i < list.length; i++) {
            list.getItem(i).isChecked.set("value", false);
        }
        var listview:RadListView =<RadListView> page.getViewById("myListView");
        listview.refresh();
    }

    JavaScript
    var observable_1 = require("data/observable");
    var observable_array_1 = require("data/observable-array");
    // Event handler for Page "navigatingTo" event attached in main-page.xml
    var vmConfig;
    var page;
    function navigatingTo(args) {
        vmConfig = new observable_1.Observable({
            myItems: new observable_array_1.ObservableArray([
                { label: "Test", isChecked: new observable_1.Observable({ value: true }) },
                { label: "Test", isChecked: new observable_1.Observable({ value: false }) },
                { label: "Test", isChecked: new observable_1.Observable({ value: true }) },
                { label: "Test", isChecked: new observable_1.Observable({ value: true }) },
                { label: "Test", isChecked: new observable_1.Observable({ value: false }) },
            ])
        });
        page = args.object;
        page.bindingContext = vmConfig;
    }
    exports.navigatingTo = navigatingTo;
    function selectAllSwitchItems() {
        var list = vmConfig.get("myItems");
        for (var i = 0; i < list.length; i++) {
            list.getItem(i).isChecked.set("value", true);
        }
        var listview = page.getViewById("myListView");
        listview.refresh();
    }
    exports.selectAllSwitchItems = selectAllSwitchItems;
    function unselectAllSwitchItems() {
        var list = vmConfig.get("myItems");
        for (var i = 0; i < list.length; i++) {
            list.getItem(i).isChecked.set("value", false);
        }
        var listview = page.getViewById("myListView");
        listview.refresh();
    }
    exports.unselectAllSwitchItems = unselectAllSwitchItems;

    In this way, the binding should work as expected on both iOS and Android.
    Regards,
    nikolay.tsonev
    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 30 Mar 2017 in reply to Nikolay Tsonev Link to this post

    Thanks, that worked.

     

    Best regards,

    Marc

Back to Top