This is a migrated thread and some comments may be shown as answers.

strange behaviour with selecting/unselecting switches within ListView on iOS

2 Answers 65 Views
ListView
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Marc
Top achievements
Rank 1
Marc asked on 28 Mar 2017, 03:47 PM

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 Answers, 1 is accepted

Sort by
0
Accepted
Nikolay Tsonev
Telerik team
answered on 29 Mar 2017, 02:49 PM
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.
0
Marc
Top achievements
Rank 1
answered on 30 Mar 2017, 04:05 PM

Thanks, that worked.

 

Best regards,

Marc

Tags
ListView
Asked by
Marc
Top achievements
Rank 1
Answers by
Nikolay Tsonev
Telerik team
Marc
Top achievements
Rank 1
Share this question
or