274

I´m fairly new to Angular2 and I have a little problem:

In my Login-Component-HTML, I have two checkboxes, which I want to bind in two way data-binding to the Login-Component-TypeScript.

This is the HTML:

<div class="checkbox">
<label>
    <input #saveUsername [(ngModel)]="saveUsername.selected" type="checkbox" data-toggle="toggle">Save username
</label>
</div>

And this is the Component.ts:

import { Component, OnInit }    from '@angular/core';
import { Router }               from '@angular/router';
import { Variables }            from '../../services/variables';

@Component({
    selector: 'login',
    moduleId: module.id,
    templateUrl: 'login.component.html',
    styleUrls: ['login.component.css']
})


export class LoginComponent implements OnInit {

    private saveUsername: boolean = true;
    private autoLogin: boolean = true;
    constructor(private router: Router, private variables: Variables) { }

    ngOnInit() { 
        this.loginValid = false;
        // Get user name from local storage if you want to save

        if (window.localStorage.getItem("username") === null) {
           this.saveUsername = true;
           this.autoLogin = true;
           console.log(this.saveUsername, this.autoLogin);
        } else {
           console.log("init", window.localStorage.getItem("username"));
        }
    }

    login(username: string, password: string, saveUsername: boolean, autoLogin: boolean) {
        this.variables.setUsername(username);
        this.variables.setPassword(password);
        this.variables.setIsLoggedIn(true);
        console.log(saveUsername, autoLogin);
        //this.router.navigate(['dashboard']);
    }

If I click an checkbox, I get the correct value in the controller (component).

But if I change the value of for example saveUsername in the component, the checkbox didn't "get" the new value.

So I can´t manipulate the checkbox from the Component (like I want to do in the ngOnInit in the component.

Thanks for your help!

pizzaisdavid
  • 455
  • 3
  • 13
Junias
  • 3,037
  • 2
  • 15
  • 21

15 Answers15

466

You can remove .selected from saveUsername in your checkbox input since saveUsername is a boolean. Instead of [(ngModel)] use [checked]="saveUsername" (change)="saveUsername = !saveUsername"

Edit: Correct Solution:

<input
  type="checkbox"
  [checked]="saveUsername"
  (change)="saveUsername = !saveUsername"/>

Update: Like @newman noticed when ngModel is used in a form it won't work. However, you should use [ngModelOptions] attribute like (tested in Angular 7):

<input
  type="checkbox"
  [(ngModel)]="saveUsername"
  [ngModelOptions]="{standalone: true}"/> `

I also created an example at Stackblitz: https://stackblitz.com/edit/angular-abelrm

Yashwardhan Pauranik
  • 5,370
  • 5
  • 42
  • 65
hakany
  • 7,134
  • 2
  • 19
  • 22
  • If i do this, then i get an error: Error: Cannot assign to a reference or variable! – Junias Oct 24 '16 at 09:38
  • hm,I´m already getting this error: Unhandled Promise rejection: Cannot assign to a reference or variable! ; Zone: ; Task: Promise.then ; Value: Error: Cannot assign to a reference or variable! And how does the checkbox knows, if it should be switched on / off? In Angular 1 i could do it like this: `$scope.loginData = {}; $scope.loginData.username = window.localStorage.getItem("username");` and this in the template: `Benutzername speichern` – Junias Oct 24 '16 at 11:13
  • could you remove #saveUsername and try again. see also plunker: http://embed.plnkr.co/ffkrDzon1L3ZANiuGFsp/ – hakany Oct 24 '16 at 11:34
  • checkbox knows because of [checked], checked will be set if saveUsername == true, and (change) updates his value with his opposite, if saveUsername is true it would be !true which is equal to false. – hakany Oct 24 '16 at 11:41
  • Hi, ok, so many thanks to you! Your last post was the solution! I edit your solution and mark it as answer ;) Thanks! – Junias Oct 24 '16 at 11:44
  • 2
    For some reasons, if the input is not inside a form, but it's part of *ngFor loop, `[(ngModel)]="saveUsername"` doesn't work, but this one works. It must be a bug in angular? – newman Feb 04 '18 at 20:31
  • 3
    This works for me while [(ngModel)] is behaving weirdly. Can someone point me to some documentation or a discussion on why [checked] is better to use than ngModel in the case of checkboxes? – vc669 Apr 09 '18 at 09:13
  • 3
    Although this is the accepted answer, it doesn't work in some contexts unless there is a 'name' attribute. Apparently any name. – Adam Wise Mar 01 '19 at 20:10
  • 3
    when `ngModel` is used in a form it won't work. `[ngModelOptions]="{standalone: true}"` is what I needed. – rainversion_3 Apr 01 '19 at 15:11
  • Awesome, first option worked like a charm ! Medal to you man ! – RohitAneja Apr 23 '20 at 07:56
  • @AdamWise answer helped me. I have a checkbox inside form in Angular 10, ngModel was not working, adding [ngModelOptions]="{standalone: true}" was throwing more errors, only thing that worked was provide a name & then ngModel would work, nothing else needed. – RDV Jun 16 '21 at 22:54
101

Unfortunately solution provided by @hakani is not two-way binding. It just handles One-way changing model from UI/FrontEnd part.

Instead the simple:

<input [(ngModel)]="checkboxFlag" type="checkbox"/>

will do two-way binding for checkbox.

Afterwards, when Model checkboxFlag is changed from Backend or UI part - voila, checkboxFlag stores actual checkbox state.

To be sure I've prepared Plunker code to present the result : https://plnkr.co/edit/OdEAPWRoqaj0T6Yp0Mfk

Just to complete this answer you should include the import { FormsModule } from '@angular/forms' into app.module.ts and add to imports array i.e

import { FormsModule } from '@angular/forms';

[...]

@NgModule({
  imports: [
    [...]
    FormsModule
  ],
  [...]
})
Jeet
  • 5,569
  • 8
  • 43
  • 75
Ruslan Makrenko
  • 1,287
  • 1
  • 9
  • 9
  • 5
    Doesn't seem to work when you are using the checkbox inside an `ngFor`, while repeating an array of objects like `[{"checked":true},{"checked":false}]` – Rohit Rane Jun 28 '17 at 09:21
  • 3
    I can't get this solution to work, I get `cUncaught Error: Template parse errors: Can't bind to 'ngModel' since it isn't a known property of 'input'` – sebnukem Jul 10 '17 at 22:14
  • 6
    @sebnukem It seems that you missing declare import for FormsModule. – teddy Jul 11 '17 at 17:39
  • 1
    @sebnukem inside a name property is required for [(ngModel)] to be used – Angela P Mar 07 '18 at 16:17
  • Will it also work for multiple checkboxes? `` – phougatv Jun 26 '18 at 10:15
  • Got the error like @sebnukem has noticed. The solution in my case was to add FormsModule, like in the answer here https://stackoverflow.com/questions/38892771/cant-bind-to-ngmodel-since-it-isnt-a-known-property-of-input/38896469#38896469 – Vadi Oct 10 '18 at 13:03
  • I got an error that it needed a name attribute. You can give it a name or you can use [ngModelOptions]="{standalone: true}" and it'll bind. – Gavin Greenwalt Nov 13 '18 at 07:26
  • Using Angular 7, I have found that using [(ngModel)] usually works, but is not a "cure-all". I had In my function handleExpirationCheckBoxChange, setting the boolean expirationCheckBox.selected got ignored unless I put it into a setTimeout call. – user2367418 Jun 29 '20 at 21:13
  • 1
    If used inside an `*ngFor` the `name` attribute has to be unique for each item in the loop. I was having issues with the default checked state because of this, once I made the `name` attribute unique, the default checked state was working as expected. – Jay Klehr Jun 30 '20 at 20:53
45

I'm working with Angular5 and I had to add the "name" attribute to get the binding to work... The "id" is not required for binding.

<input type="checkbox" id="rememberMe" name="rememberMe" [(ngModel)]="rememberMe">
Kris Kilton
  • 938
  • 9
  • 11
  • 3
    This answer worked for me. Other answers are also correct. But with [(ngModel)] we don't have to write a separate function to switch the boolean – Jasmeet Nov 08 '18 at 17:42
42

I prefer something more explicit:

component.html

<input #saveUserNameCheckBox
    id="saveUserNameCheckBox" 
    type="checkbox" 
    [checked]="saveUsername" 
    (change)="onSaveUsernameChanged(saveUserNameCheckBox.checked)" />

component.ts

public saveUsername:boolean;

public onSaveUsernameChanged(value:boolean){
    this.saveUsername = value;
}
MovGP0
  • 7,267
  • 3
  • 49
  • 42
11

You can just use something like this to have two way data binding:

<input type="checkbox" [checked]="model.property" (change)="model.property = !model.consent_obtained_ind">
pizzaisdavid
  • 455
  • 3
  • 13
Nuno Ferro
  • 1,261
  • 12
  • 17
7
Angular: "9.0.0"
Angular CLI: 9.0.1
Node: 13.10.1
OS: linux x64

.html file

<input [(ngModel)]="userConsent" id="userConsent" required type="checkbox"/> " I Accept"

.ts file

userConsent: boolean = false;
khizer
  • 1,242
  • 15
  • 13
6

When using <abc [(bar)]="foo"/> syntax on angular.

This translates to: <abc [bar]="foo" (barChange)="foo = $event" />

Which means your component should have:

@Input() bar;
@Output() barChange = new EventEmitter();
slfan
  • 8,950
  • 115
  • 65
  • 78
4

To get checkbox work you should follow all these steps:

  1. import FormsModule in your module
  2. Put the input inside a form tag
  3. your input should be like this:

    <input name="mpf" type="checkbox" [(ngModel)]="value" />
    

    Note: do not forget to put name in your input.

Mahdi Shahbazi
  • 1,063
  • 1
  • 10
  • 13
3

I have done a custom component tried two way binding

Mycomponent: <input type="checkbox" [(ngModel)]="model" >

_model:  boolean;   

@Output() checked: EventEmitter<boolean> = new EventEmitter<boolean>();

@Input('checked')
set model(checked: boolean) {

  this._model = checked;
  this.checked.emit(this._model);
  console.log('@Input(setmodel'+checked);
}

get model() {
  return this._model;
}

strange thing is this works

<mycheckbox  [checked]="isChecked" (checked)="isChecked = $event">

while this wont

<mycheckbox  [(checked)]="isChecked">
andolsi zied
  • 3,553
  • 2
  • 32
  • 43
user1786641
  • 101
  • 13
3

You must add name="selected" attribute to input element.

For example:

<div class="checkbox">
  <label>
    <input name="selected" [(ngModel)]="saveUsername.selected" type="checkbox">Save username
  </label>
</div>
pizzaisdavid
  • 455
  • 3
  • 13
m.shakeri
  • 1,203
  • 1
  • 12
  • 16
3

I know it may be repeated answer but for any one want to load list of checkboxes with selectall checkbox into angular form i follow this example: Select all/deselect all checkbox using angular 2+

it work fine but just need to add

[ngModelOptions]="{standalone: true}" 

the final HTML should be like this:

<ul>
    <li><input type="checkbox" [(ngModel)]="selectedAll" (change)="selectAll();"/></li>
    <li *ngFor="let n of names">
    <input type="checkbox" [(ngModel)]="n.selected" (change)="checkIfAllSelected();">{{n.name}}
    </li>
  </ul>

TypeScript

  selectAll() {
    for (var i = 0; i < this.names.length; i++) {
      this.names[i].selected = this.selectedAll;
    }
  }
  checkIfAllSelected() {
    this.selectedAll = this.names.every(function(item:any) {
        return item.selected == true;
      })
  }

hope this help thnx

taha mosaad
  • 567
  • 5
  • 13
2

In any situation, if you have to bind a value with a checkbox which is not boolean then you can try the below options

In the Html file:

<div class="checkbox">
<label for="favorite-animal">Without boolean Value</label>
<input type="checkbox" value="" [checked]="ischeckedWithOutBoolean == 'Y'" 
(change)="ischeckedWithOutBoolean = $event.target.checked ? 'Y': 'N'">
</div>

in the componentischeckedWithOutBoolean: any = 'Y';

See in the stackblitz https://stackblitz.com/edit/angular-5szclb?embed=1&file=src/app/app.component.html

Sabbir
  • 327
  • 5
  • 14
1

My angular directive like angularjs (ng-true-value ng-false-value)

@Directive({
    selector: 'input[type=checkbox][checkModel]'
})
export class checkboxDirective {
    @Input() checkModel:any;
    @Input() trueValue:any;
    @Input() falseValue:any;
    @Output() checkModelChange = new EventEmitter<any>();

    constructor(private el: ElementRef) { }

    ngOnInit() {
       this.el.nativeElement.checked = this.checkModel==this.trueValue;
    }

    @HostListener('change', ['$event']) onChange(event:any) {
        this.checkModel = event.target.checked ? this.trueValue : this.falseValue;
        this.checkModelChange.emit(this.checkModel);
    }

}

html

<input type="checkbox" [(checkModel)]="check" [trueValue]="1" [falseValue]="0">
  • 1
    Hi, please explain your problem, what have you tried and add some context to your question – TOPKAT Aug 28 '19 at 19:43
1

In Angular p-checkbox,

Use all attributes of p-checkbox

<p-checkbox name="checkbox" value="isAC" 
    label="All Colors" [(ngModel)]="selectedAllColors" 
    [ngModelOptions]="{standalone: true}" id="al" 
    binary="true">
</p-checkbox>

And more importantly, don't forget to include [ngModelOptions]="{standalone: true} as well as it SAVED MY DAY.

Dante
  • 295
  • 2
  • 12
Taimoor Tahir
  • 430
  • 4
  • 6
0

A workaround to achieve the same specially if you want to use checkbox with for loop is to store the state of the checkbox inside an array and change it based on the index of the *ngFor loop. This way you can change the state of the checkbox in your component.

app.component.html

<div *ngFor="let item of items; index as i"> <input type="checkbox" [checked]="category[i]" (change)="checkChange(i)"> {{item.name}} </div>

app.component.ts

items = [
    {'name':'salad'},
    {'name':'juice'},
    {'name':'dessert'},
    {'name':'combo'}
  ];

  category= []

  checkChange(i){
    if (this.category[i]){  
      this.category[i] = !this.category[i];
    }
    else{
      this.category[i] = true;
    }
  }
Sid
  • 9
  • 1
  • 3