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?

FacundoGFlores
fonte
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.

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

Kaloyan Stamatov
fonte
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();
}
Anuj TBE
fonte
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();

Ignacio Ara
fonte
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.

Tilak Bhandari
fonte
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();
}
Recep Duman
fonte
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)
Pu ChengLie
fonte
1

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

Exari Constantin
fonte
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>
Sagar Jadhav
fonte
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 .

Kedar9444
fonte
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.

somesh T
fonte
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" />
Frank Corona
fonte
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()">
Saad Abbasi
fonte
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()
Aleksandr Zelenskiy
fonte
-1

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

Taha Zgued
fonte
-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.
  })
}
user3345544
fonte