Ligação de dados em dois sentidos da caixa de seleção angular 2

203

Sou relativamente novo no Angular2 e tenho um pequeno problema:

No meu Login-Component-HTML, tenho duas caixas de seleção, que desejo vincular de maneira bidirecional à vinculação de dados ao Login-Component-TypeScript.

Este é o HTML:

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

E este é o 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']);
    }

Se clicar em uma caixa de seleção, obtenho o valor correto no controlador (componente).

Mas se eu alterar o valor de, por exemplo, saveUsernameno componente, a caixa de seleção não "obterá" o novo valor.

Portanto, não posso manipular a caixa de seleção do Componente (como quero fazer no ngOnInitno componente.

Obrigado pela ajuda!

Junias
fonte
Verifique aqui o exemplo do Angular 7 de ligação da caixa de seleção freakyjolly.com/…
Code Spy

Respostas:

353

Você pode remover .selectedde saveUsernamesua entrada da caixa de seleção, pois saveUsername é um booleano. Em vez de [(ngModel)]usar[checked]="saveUsername" (change)="saveUsername = !saveUsername"

Editar: Solução correta:

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

Atualização: como o @newman notou quando ngModelé usado em um formulário, ele não funciona. No entanto, você deve usar [ngModelOptions]atributos como (testados no Angular 7):

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

Também criei um exemplo no Stackblitz: https://stackblitz.com/edit/angular-abelrm

hakany
fonte
Se fizer isso, recebo um erro: Erro: Não é possível atribuir a uma referência ou variável!
Júnias
hm, já estou recebendo este erro: Não tratado Rejeição de promessa: Não é possível atribuir a uma referência ou variável! ; Zona: <raiz>; Tarefa: Promise.then; Valor: Erro: Não é possível atribuir a uma referência ou variável! E como a caixa de seleção sabe se deve ser ativada / desativada? No Angular 1 eu poderia fazer assim: $scope.loginData = {}; $scope.loginData.username = window.localStorage.getItem("username");e isso no modelo:<ion-toggle ng-model="saveUsername" ng-change="toggleSaveUsername()" toggle-class="toggle-energized">Benutzername speichern</ion-toggle>
Junias 24/10
1
Por algumas razões, se a entrada não estiver dentro de um formulário, mas fizer parte do loop * ngFor, [(ngModel)]="saveUsername"não funcionará, mas esta funcionará. Deve ser um bug em angular?
newman
1
Isso funciona para mim enquanto [(ngModel)] está se comportando de maneira estranha. Alguém pode me indicar alguma documentação ou discussão sobre por que [marcado] é melhor usar do que o ngModel no caso de caixas de seleção?
Vc669
3
quando ngModelé usado em um formulário, não funciona. [ngModelOptions]="{standalone: true}"é o que eu precisava.
Rainversion_3 01/04/19
88

Infelizmente, a solução fornecida por @hakani não é uma ligação de mão dupla . Ele apenas lida com o modelo de mudança unidirecional da parte UI / FrontEnd.

Em vez disso, o simples:

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

fará ligação bidirecional para a caixa de seleção.

Posteriormente, quando o modelo checkboxFlag é alterado do backend ou da parte da interface do usuário - voila, o checkboxFlag armazena o estado real da caixa de seleção.

Para garantir que eu preparei o código Plunker para apresentar o resultado: https://plnkr.co/edit/OdEAPWRoqaj0T6Yp0Mfk

Apenas para concluir esta resposta, você deve incluir o array import { FormsModule } from '@angular/forms'into app.module.tse add to imports, ou seja,

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

[...]

@NgModule({
  imports: [
    [...]
    FormsModule
  ],
  [...]
})
Ruslan Makrenko
fonte
3
Não parece trabalho quando você estiver usando a caixa de seleção dentro de um ngFor, enquanto repetindo uma matriz de objetos como[{"checked":true},{"checked":false}]
jackOfAll
Eu não posso começar esta solução para o trabalho, eu ficocUncaught Error: Template parse errors: Can't bind to 'ngModel' since it isn't a known property of 'input'
sebnukem
5
@sebnukem Parece que você está declarando falta de importação para o FormsModule.
pelúcia
@sebnukem dentro <input> a propriedade de nome é exigido para [(ngModel)] para ser usado
Angela Pan
Também funcionará para várias caixas de seleção? <input type="checkbox" [(ngModel)]="day.IsChecked" [checked]="day.IsChecked" />
barnes
35

Estou trabalhando com o Angular5 e tive que adicionar o atributo "name" para fazer a ligação funcionar ... O "id" não é necessário para a ligação.

<input type="checkbox" id="rememberMe" name="rememberMe" [(ngModel)]="rememberMe">
Kris Kilton
fonte
1
Essa resposta funcionou para mim. Outras respostas também estão corretas. Mas com [(ngModel)] não temos que escrever uma função separada para mudar o boolean
Jasmeet
25

Eu prefiro algo mais explícito:

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
fonte
2
A única coisa em todo esse segmento que funcionou. Obrigado! Usando Angular 8.2.11.
daka
Esta resposta deve estar no topo.
harshit raghav
1
salvar meu dia :-)
hannes neukermans
6

Ao usar a <abc [(bar)]="foo"/>sintaxe em angular.

Isso se traduz em: <abc [bar]="foo" (barChange)="foo = $event" />

O que significa que seu componente deve ter:

@Input() bar;
@Output() barChange = new EventEmitter();
Jose Alberto Fernandez
fonte
resposta é muito bem - curta e clara, mas deve sob a outra pergunta
Nikita
5

Você pode usar algo assim para ter uma ligação de dados bidirecional:

<input type="checkbox" [checked]="model.property" (change)="model.property = !model.consent_obtained_ind">
Nuno Ferro
fonte
3

Para que a caixa de seleção funcione, siga todas estas etapas:

  1. importar FormsModule no seu módulo
  2. Coloque a entrada dentro de uma formtag
  3. sua entrada deve ser assim:

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

    Nota: não esqueça de colocar o nome na sua entrada.

Mahdi Shahbazi
fonte
3

Você deve adicionar name="selected"atributo ao inputelemento.

Por exemplo:

<div class="checkbox">
  <label>
    <input name="selected" [(ngModel)]="saveUsername.selected" type="checkbox">Save username
  </label>
</div>
M.Shakeri
fonte
2

Eu fiz um componente personalizado tentei ligação em dois sentidos

Meucomponente: <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;
}

coisa estranha é que isso funciona

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

enquanto isso não

<mycheckbox  [(checked)]="isChecked">
user1786641
fonte
1

Em qualquer situação, se você precisar vincular um valor a uma caixa de seleção que não seja booleana, tente as opções abaixo

No arquivo HTML:

<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>

no componenteischeckedWithOutBoolean: any = 'Y';

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

Sabbir
fonte
1

Sei que pode ser uma resposta repetida, mas para quem quiser carregar a lista de caixas de seleção com a caixa de seleção em forma angular, sigo este exemplo: Marque todas / desmarque todas as caixas de seleção usando angular 2+

funciona bem, mas só precisa adicionar

[ngModelOptions]="{standalone: true}" 

o HTML final deve ser assim:

<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;
      })
  }

espero que isso ajude thnx

taha mosaad
fonte
0

Uma solução alternativa para obter o mesmo, especialmente se você deseja usar a caixa de seleção com loop for, é armazenar o estado da caixa de seleção em uma matriz e alterá-la com base no índice do *ngForloop. Dessa forma, você pode alterar o estado da caixa de seleção no seu componente.

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
fonte
0

Minha diretiva angular como 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">
Edgardo Rivera
fonte
Oi, por favor, explique o seu problema, o que você tentou e adicionar algum contexto à sua pergunta
538ROMEO
0

Na caixa de seleção p angular,

Use todos os atributos da caixa de seleção p

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

E o mais importante, não se esqueça de incluir [ngModelOptions]="{standalone: true}, além de salvar o meu dia.

Mian Taimoor Tahir
fonte
0
Angular: "9.0.0"
Angular CLI: 9.0.1
Node: 13.10.1
OS: linux x64

arquivo .html

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

arquivo .ts

userConsent: boolean = false;
Khizer
fonte