Formulários reativos - atributo desativado


97

Estou tentando usar o disabledatributo de a formControl. Quando eu coloco no template, funciona:

<md-input formControlName="id" placeholder="ID" [disabled]="true"></md-input>

Mas o navegador me alerta:

Parece que você está usando o atributo disabled com uma diretiva de formulário reativa. Se você definir disabled como true ao configurar este controle em sua classe de componente, o atributo disabled será realmente definido no DOM para você. Recomendamos o uso dessa abordagem para evitar erros "alterado após verificação".

  Example: 
  form = new FormGroup({
    first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
    last: new FormControl('Drew', Validators.required)
  });

Então, eu coloquei no FormControle excluí do modelo:

constructor(private itemsService: ItemsService) {
    this._items = [];
    this.myForm = new FormGroup({
        id: new FormControl({value: '', disabled: true}, Validators.required),
        title: new FormControl(),
        description: new FormControl()
    });
    this.id = this.myForm.controls['id'];
    this.title = this.myForm.controls['title'];
    this.description = this.myForm.controls['description'];
    this.id.patchValue(this._items.length);
}

Mas não funciona (não está desabilitando o input). Qual é o problema?


1
Isso parece funcionar bem com a versão atual do Angular 2: plnkr.co/edit/CQQtkYC9D5EoH0sAlNCV?p=preview
silentsod

Estou usando o
último

2
Você está usando @ angular / material, portanto, de acordo com os problemas do github: github.com/angular/material2/issues/1171 Ainda não é compatível e está em alfa, então você não pode esperar que o recurso esteja completo.
silentsod

Sim, era o problema
FacundoGFlores

6
Você pode tentar colocar this.myForm.controls['id'].disable()em algum lugar no construtor. Fiz uma biblioteca que torna mais fácil trabalhar com formulários dinâmicos: github.com/mat3e/dorf
mat3e

Respostas:


116

Eu tenho usado [attr.disabled]porque ainda gosto deste template orientado ao invés de programático enable () / disable (), pois é IMO superior.

mudança

<md-input formControlName="id" placeholder="ID" [disabled]="true"></md-input>

para

<md-input formControlName="id" placeholder="ID" [attr.disabled]="true"></md-input>

Se você estiver usando um material mais recente, mude md-inputpara mat-input.


1
Funciona, obrigado! Mas eu não entendo por que devo usar "attr.disabled" (não apenas "disabled").
Sergey Andreev

6
Apenas para observar, com [attr.disabled] você não pode usar o bind de duas maneiras. Só funciona uma vez. Com [disabled]e o aviso no console está funcionando. Estou usando o Angular 4.1.3
The.Bear de

2
Acho que isso [attr.disabled]simplesmente não aciona o aviso que [disabled]mostra
K1ngjulien_

3
Você pode explicar por que você acha que é "superior"?
Lazar Ljubenović

1
As propriedades do campo do formulário podem ser lidas no modelo HTML. Digamos que um belo dia você decida observar o que desativa um determinado campo - o instinto é caminhar do modelo HTML para o código datilografado do que as outras maneiras.
bhantol 01 de

13

Você pode ativar / desativar um controle de formulário usando os seguintes métodos:

control.disable () ou control.enable ()

Se isso não funcionar, você pode usar uma diretiva

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

@Directive({
  selector: '[disableControl]'
})
export class DisableControlDirective {

  @Input() set disableControl( condition : boolean ) {
    const action = condition ? 'disable' : 'enable';
    this.ngControl.control[action]();
  }

  constructor( private ngControl : NgControl ) {
  }

}

Então você poderia usá-lo assim

<input [formControl]="formControl" [disableControl]="disable">
<button (click)="disable = true">Disable</button>
<button (click)="disable = false">Enable</button>

Esta técnica é descrita aqui:

https://netbasal.com/disabling-form-controls-when-working-with-reactive-forms-in-angular-549dd7b42110

Espero que ajude


você pode mostrar algum trecho de código js como fazer isso
kumaresan_sd

forneça quaisquer amostras
stackb

aqui está um exemplo: netbasal.com/…
Janatbek Sharsheyev

Isso não funciona com o Angular 8. DáNgControl (`No provider for NgControl`)
pantonis

1
Posso confirmar que esta solução não funciona mais a partir do Angular 8 !!
Martijn Hiemstra


9

No meu caso com o Angular 8 . Eu queria ativar / desativar a entrada dependendo da condição.

[attr.disabled] não funcionou para mim, então aqui está a minha solução.

Eu removi [attr.disabled]do HTML e na função do componente executei esta verificação:

if (condition) {
    this.form.controls.myField.disable();
} else {
    this.form.controls.myField.enable();
}

4

Inicialização (componente) usando:

public selector = new FormControl({value: '', disabled: true});

Então, em vez de usar (template):

<ngx-select
[multiple]="true"
[disabled]="errorSelector"
[(ngModel)]="ngxval_selector"
[items]="items"
</ngx-select>

Basta remover o atributo desativado:

<ngx-select
[multiple]="true"
[(ngModel)]="ngxval_selector"
[items]="items"
</ngx-select>

E quando você tiver itens para mostrar, inicie (no componente): this.selector.enable();


2

Apenas quem está usando formulários reativos: Para elementos HTML nativos [attr.disabled] funcionará, mas para elementos materiais, precisamos desativar dinamicamente o elemento.

this.form.get('controlname').disable();

Caso contrário, ele será mostrado na mensagem de aviso do console.


2

Eu tentei isso no angular 7. Funcionou com sucesso.

this.form.controls['fromField'].reset();
if(condition){
      this.form.controls['fromField'].enable();
}
else{
      this.form.controls['fromField'].disable();
}

2
this.form.disable()
this.form.enable()

Para um formulário, o controle torna desabilitado

this.form.get('first').disable()
this.form.get('first').enable()

Ou método de definição inicial.

first: new FormControl({disabled: true}, Validators.required)

1

Use [attr.disabled] em vez [disabled], no meu caso funciona bem


2
Embora isso seja possível, você não deve usar uma solução orientada por modelo ao trabalhar com formulários reativos. O problema de misturar os dois é que o estado de forma reativa não é mais confiável.
enf0rcer de

ele usa para desabilitar, mas se eu definir isso como falso também controlar obter desabilitar
kumaresan_sd

1

adicionar disable = "true" ao campo html Exemplo: desativar

<amexio-text-input formControlName="LastName" disable="true" [(ngModel)]="emplpoyeeRegistration.lastName" [field-label]="'Last Name'" [place-holder]="'Please enter last name'" [allow-blank]="true" [error-msg]="'errorMsg'" [enable-popover]="true" [min-length]="2"
[min-error-msg]="'Minimum 2 char allowed'" [max-error-msg]="'Maximum 20 char allowed'" name="xyz" [max-length]="20">
[icon-feedback]="true">
</amexio-text-input>

Não está funcionando . exemplo de link - stackblitz.com/edit/angular-zdpavf?file=src/app/…
kumaresan_sd

Esta resposta não funcionará na forma reativa. Isso está relacionado à forma orientada por modelo
Nambi N Rajan

1

A beleza das formas reativas é que você pode capturar eventos de alterações de valores de qualquer elemento de entrada com muita facilidade e, ao mesmo tempo, alterar seus valores / status. Portanto, aqui está uma outra maneira de resolver seu problema usando enable disable.

Aqui está a solução completa no stackblitz .


Eu sugiro que você poste o código aqui também, ou pelo menos um snippet. Achei essa solução útil, então assinar a alteração de valor e ativar / desativar parece uma boa opção.
John White

1

a desativação de campos de formulário de esteira está isenta se você estiver usando a validação de formulário, portanto, certifique-se de que seu campo de formulário não tenha validações como (validators.required), isso funcionou para mim. por ex:

editUserPhone: new FormControl ({value: '', disabled: true})

isso torna os números de telefone do usuário não editáveis.


1

Esta foi a minha solução:

this.myForm = this._formBuilder.group({
    socDate: [[{ value: '', disabled: true }], Validators.required],
    ...
)}

<input fxFlex [matDatepicker]="picker" placeholder="Select Date" formControlName="socDate" [attr.disabled]="true" />

1
Olá, Frank, bem-vindo ao StackOverflow e obrigado pela sua resposta! Embora seja certamente ótimo fornecer uma solução funcional no código, ele pode ajudar outras pessoas agora e no futuro a compreender melhor sua resposta se você adicionar um pouco de explicação além do código.
robsiemb

1

no Angular-9, se você deseja habilitar / desabilitar no botão, clique aqui é uma solução simples se você estiver usando formas reativas.

definir uma função no arquivo component.ts

//enable example you can use the same approach for disable with .disable()

toggleEnable() {
  this.yourFormName.controls.formFieldName.enable();
  console.log("Clicked")
} 

Chame-o de seu component.html

por exemplo

<button type="button" data-toggle="form-control" class="bg-primary text-white btn- 
                reset" style="width:100%"(click)="toggleEnable()">

0

Ao criar um novo controle de formulário, use próximo:

variable: FormControl = new FormControl({value: '', disabled: true});

Se você quiser mudar a atividade, use a seguir:

this.variable.enable() 

ou

this.variable.disable()

-1

adicione o atributo de nome à sua entrada MD. se não resolver o problema, poste seu modelo


-4

A melhor maneira de fazer isso.

ngOnInit() {
  this.interPretationForm.controls.InterpretationType.valueChanges.takeWhile(()=> this.alive).subscribe(val =>{
    console.log(val); // You check code. it will be executed every time value change.
  })
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.