Ionic-framework: ngModel not working on ion-checkbox and ion-toggle, have to watch for click event

Created on 18 Jan 2016  Â·  28Comments  Â·  Source: ionic-team/ionic-framework

_From @colinjlacy on January 1, 2016 19:2_

Hi, I'm having trouble trying to apply the ngModel directive to ion-toggle and ion-checkbox. If I try the following:

<ion-toggle [(ngModel)]="listItem.active">{{listItem.name}}</ion-toggle>

I get the this error:

screen shot 2015-12-31 at 11 06 55 am

I was able to get it to work by binding one-way to the checked property, and then listening for a (click) with a component event handler:

<ion-toggle checked="{{listItem.active}}" (click)="toggleActive(listItem)">{{listItem.name}}</ion-toggle>

Am I missing something or is this the intended functionality? And if it is that's totally fine; I'm just wondering if this is the way I should implement going forward.

_Copied from original issue: driftyco/ionic2#842_

Most helpful comment

I'd like to say that adding this option [ngModelOptions]="{standalone: true}" solves the problem, the whole markup is written this way

<ion-toggle color="positive" [(ngModel)]="removeLogo" [ngModelOptions]="{standalone: true}"></ion-toggle>

All 28 comments

_From @brandyscarney on January 1, 2016 19:53_

The way you had it the first time is the intended way to write it. This is a bug. I think it is the same issue as #819, which I am unable to reproduce in local tests so I believe it has been fixed in a previous refactor. We just need to get a stable release together to find out.

_From @phavre on January 1, 2016 20:24_

I Hope this will also solve a similar issue with the searchbar which is not working either for the same reason (object has change after it was checked). Had to bind the list item with a class attribute hidden to filter the non matching lines. But we're in a beta anyway the framework is terrific, keep up the good work !

_From @brandyscarney on January 1, 2016 20:30_

That exception shouldn't be breaking anything. It is being thrown on a lot of components right now but they still work as desired. The issue with this is caused by something else. Can you paste your code for the searchbar and compare it to the conference app?

https://github.com/driftyco/ionic-conference-app/blob/master/app/pages/schedule/schedule.html#L24-L28
https://github.com/driftyco/ionic-conference-app/blob/master/app/pages/schedule/schedule.js#L36-L41

_From @dupski on January 2, 2016 0:16_

+1
I get the exact same exception using ion-toggle with ngControl and a ControlGroup. I have also tried with ion-checkbox and a vanilla checkbox and got similar issues, so I'm wondering if this is an Angular2 problem?

<ion-toggle ngControl="use_ssl">Use SSL?</ion-toggle>

I currently have to use:

<ion-toggle #chk1 [checked]="settingsForm.controls['use_ssl'].value"
    (click)="settingsForm.controls['use_ssl'].updateValue(chk1.checked)">Use SSL?</ion-toggle>

Which ain't pretty! :)

My ionic info:
Cordova CLI: 5.4.1
Gulp version: CLI version 3.9.0
Gulp local: Local version 3.9.0
Ionic Version: 2.0.0-alpha.45
Ionic CLI Version: 2.0.0-beta.15
Ionic App Lib Version: 2.0.0-beta.8
OS: Distributor ID: Ubuntu Description: Ubuntu 14.04.3 LTS
Node Version: v4.2.4

_From @colinjlacy on January 2, 2016 1:7_

Yeah it's the same for toggle and checkbox. Thanks for the quick reply, looking forward to the fix.

_From @phavre on January 3, 2016 20:26_

Indeed @brandyscarney when implementing the searchBar the way it has been done in the links you supplied, it works like a charm.
I originally followed the searchbar component demo source and this one gives me the error (it it functioning ?) I couldn't understand how the getItem function could be called for the view to be refreshed (But in the link provided it was clear with the input bind function)

_From @brandyscarney on January 4, 2016 3:6_

The component demos are a little behind master right now. We're constantly changing things in the source code and it's hard to keep the demos up to date all of the time. We try to keep the conference app up to date with the latest stable release and all component test folders should reflect master. For example, the searchbar test folder is here with different test cases:

https://github.com/driftyco/ionic2/tree/master/ionic/components/searchbar/test

And you can follow these instructions to run the source code and view all of the component tests:

https://github.com/driftyco/ionic2/blob/master/scripts/README.md#building--running-ionic-source

_From @DrMabuse23 on January 4, 2016 7:56_

On ion-segment same error

_From @phavre on January 5, 2016 16:24_

Thanks for the precious advice @brandyscarney I'll focus from now on, on the links provided to help me.
Cheers

_From @dupski on January 5, 2016 16:38_

I'll give it a test on the latest build, hopefully later this week or at the weekend at the latest and report back. Thanks :)

_From @dupski on January 6, 2016 11:53_

Hi Guys

This issue is still occurring for me with the latest alpha (47) and the following set up:

import {FormBuilder, Validators, ControlGroup} from 'angular2/common';
...
export class SettingsPage {
    settingsForm: ControlGroup;

    constructor(
        fb: FormBuilder) {

        this.settingsForm = fb.group({
            host: [null, Validators.required],
            port: [null, Validators.required],
            use_ssl: [],
        });
...

And in the template:

<form [ngFormModel]="settingsForm" (submit)="saveSettings($event)">
<ion-list>
    <ion-input stacked-label>
        <ion-label>Server Address</ion-label>
        <input type="text" ngControl="host">
    </ion-input>
    <ion-input stacked-label>
        <ion-label>Port</ion-label>
        <input type="text" ngControl="port">
    </ion-input>

    <ion-toggle ngControl="use_ssl">Use SSL?</ion-toggle>
</ion-list>
</form>
...

The exception that is raised:

ORIGINAL EXCEPTION: Expression 'checked in SettingsPage@26:1' has changed after it was checked. Previous value: 'undefined'. Current value: 'true'BrowserDomAdapter.logError @ app.bundle.js:33698ExceptionHandler.call @ app.bundle.js:7835(anonymous function) @ app.bundle.js:16808NgZone._notifyOnError @ app.bundle.js:17449collection_1.StringMapWrapper.merge.onError @ app.bundle.js:17344run @ app.bundle.js:1186(anonymous function) @ app.bundle.js:17362NgZone.run @ app.bundle.js:17311(anonymous function) @ app.bundle.js:16900schedulerFn @ app.bundle.js:15538tryCatcher @ app.bundle.js:16095Subscriber.next @ app.bundle.js:16051Subject._next @ app.bundle.js:15733Subject.next @ app.bundle.js:15696EventEmitter.emit @ app.bundle.js:15527(anonymous function) @ app.bundle.js:17204run @ app.bundle.js:1183NgZone._notifyOnTurnDone @ app.bundle.js:17204(anonymous function) @ app.bundle.js:17376zoneBoundFn @ app.bundle.js:1156lib$es6$promise$asap$$flush @ app.bundle.js:2350
app.bundle.js:33698 ORIGINAL STACKTRACE:BrowserDomAdapter.logError @ app.bundle.js:33698ExceptionHandler.call @ app.bundle.js:7838(anonymous function) @ app.bundle.js:16808NgZone._notifyOnError @ app.bundle.js:17449collection_1.StringMapWrapper.merge.onError @ app.bundle.js:17344run @ app.bundle.js:1186(anonymous function) @ app.bundle.js:17362NgZone.run @ app.bundle.js:17311(anonymous function) @ app.bundle.js:16900schedulerFn @ app.bundle.js:15538tryCatcher @ app.bundle.js:16095Subscriber.next @ app.bundle.js:16051Subject._next @ app.bundle.js:15733Subject.next @ app.bundle.js:15696EventEmitter.emit @ app.bundle.js:15527(anonymous function) @ app.bundle.js:17204run @ app.bundle.js:1183NgZone._notifyOnTurnDone @ app.bundle.js:17204(anonymous function) @ app.bundle.js:17376zoneBoundFn @ app.bundle.js:1156lib$es6$promise$asap$$flush @ app.bundle.js:2350
app.bundle.js:33698 Error: Expression 'checked in SettingsPage@26:1' has changed after it was checked. Previous value: 'undefined'. Current value: 'true'
    at ExpressionChangedAfterItHasBeenCheckedException.BaseException [as constructor] (http://192.168.220.152:8100/build/js/app.bundle.js:7704:24)
    at new ExpressionChangedAfterItHasBeenCheckedException (http://192.168.220.152:8100/build/js/app.bundle.js:12494:17)
    at AbstractChangeDetector.throwOnChangeError (http://192.168.220.152:8100/build/js/app.bundle.js:14124:16)
    at AbstractChangeDetector.ChangeDetector_SettingsPage_0.detectChangesInRecordsInternal (eval at <anonymous> (http://192.168.220.152:8100/build/js/app.bundle.js:14596:17), <anonymous>:938:16)
    at AbstractChangeDetector.detectChangesInRecords (http://192.168.220.152:8100/build/js/app.bundle.js:13949:19)
    at AbstractChangeDetector.runDetectChanges (http://192.168.220.152:8100/build/js/app.bundle.js:13926:15)
    at AbstractChangeDetector._detectChangesInViewChildren (http://192.168.220.152:8100/build/js/app.bundle.js:14018:19)
    at AbstractChangeDetector.runDetectChanges (http://192.168.220.152:8100/build/js/app.bundle.js:13930:15)
    at AbstractChangeDetector._detectChangesContentChildren (http://192.168.220.152:8100/build/js/app.bundle.js:14011:19)
    at AbstractChangeDetector.runDetectChanges (http://192.168.220.152:8100/build/js/app.bundle.js:13927:15)

Maybe it is still fixed in latest master, I'll have a play with a checkout at the weekend.

_From @brandyscarney on January 6, 2016 17:14_

So for the original issue, this works for ngModel to check the toggle by default:

html:

<ion-toggle value="apple" [(ngModel)]="myModel">
  I'm an NgModel
</ion-toggle>

where the JS is:

this.myModel = true;

so right now the ngModel needs to be a boolean to check by default.

I can see in our use case that the toggle with ngControl isn't being checked when it should in this example:

<ion-toggle value="apple" checked="true" ngControl="appleCtrl">
  Apple, value=apple, init checked
</ion-toggle>

We're going to talk with the Angular team today about this.

_From @colinjlacy on January 8, 2016 1:40_

Thanks for your input. Unfortunately I'm not seeing the same results. I've got the ion-toggle set up as you have it:

<ion-toggle value="apple" [(ngModel)]="listItem.active">Active</ion-toggle>

My interface says that the value is a boolean:

export interface ListItem {
    id: number,
    name: string,
    media: string,
    latitude: string,
    longitude: string,
    active: boolean
}

Could it have something to do with the fact that I'm loading the value from a data service instead of a binding attribute?

onPageWillEnter() {
    this._service.getItem(this.id).then(item => {
        this.listItem = item;
    });
}

Is anyone still getting issues on this using alpha.53? https://github.com/driftyco/ionic/blob/2.0/CHANGELOG.md

cc @colinjlacy @phavre @dupski @DrMabuse23

Nope ion-toggle and ngmodel work fine

Regards
Patrice

Le 1 févr. 2016 à 20:26, Brandy Carney [email protected] a écrit :

Is anyone still getting issues on this using alpha.53? https://github.com/driftyco/ionic/blob/2.0/CHANGELOG.md

cc @colinjlacy @phavre @dupski @DrMabuse23

—
Reply to this email directly or view it on GitHub.

I can confirm my issue with ion-toggle and ngControl is now resolved with the latest alpha. Cheers! :)

@colinjlacy I am also having a problem with ion-toggle, but only when loaded from a dataservice, and only when the initial status from the dataservice is checked.

Did you get yours working with a data service?

Closing this as I haven't heard any more issues about it. We are going to be working on toggle some more but feel free to open an issue if you think there is one @alexbainbridge, thanks!

@brandyscarney Sorry for being out of touch, was on vacation and wasn't allowed near my computer. Trying with alpha.53 works for me when loading from a data service. Thanks for the help. @alexbainbridge , happy to share my code with you to show you how I got it working.

@colinjlacy I have put up some sample code based on the Ionic starter on https://github.com/driftyco/ionic/issues/5428 Its probably me, but I get constant on off status setting for the ion-toggle, when using an external data source, when the external data source is true..... thoughts appreciated!

hi ! I see this issue was closed, and I don't understand why, since this still doesn't work. Even the simplest example is failing.

In my html
<ion-label>Confirmed:</ion-label> <ion-checkbox ng-model="confirmed"></ion-checkbox> <h4> value is: {{confirmed}}</h4>

in my js

`export class WelcomePage implements OnInit {

private confirmed:boolean;

constructor(protected nav: NavController, private params:NavParams) {
    super(nav);
}

ngOnInit() {
    this.confirmed = true;
}

}`

@sonoman The correct markup for it is:

<ion-checkbox [(ngModel)]="confirmed"></ion-checkbox> 

Please refer to the Angular 2 cheatsheet: https://angular.io/docs/ts/latest/guide/cheatsheet.html

Thanks!

Thanks, that worked !

@brandyscarney Hi, also having the same problem with the ion-checkbox. Tried from v2 docs:

<ion-item>
    <ion-label>Daenerys Targaryen</ion-label>
    <ion-checkbox color="dark" checked="true"></ion-checkbox>
  </ion-item>

and from v1
<ion-checkbox ng-model="filter.red">Red</ion-checkbox>

neither are working. Currently using angular 1, so the answer given for sonoman doesn't work for me either. Thanks for any help

I'd like to say that adding this option [ngModelOptions]="{standalone: true}" solves the problem, the whole markup is written this way

<ion-toggle color="positive" [(ngModel)]="removeLogo" [ngModelOptions]="{standalone: true}"></ion-toggle>

Hi, am having hard time comparing selected checkbox by clicking a button to display an alert in my ion app
i have already designed it but finding it hard to code it ..pls any assistance?

Can confirm [ngModelOptions]="{standalone: true} fixes the issue. I think this is a bug on the ionic end, and should probably be handled by you guys.

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

Was this page helpful?
0 / 5 - 0 ratings