Formas reactivas - atributo deshabilitado

97

Estoy tratando de usar el disabledatributo de a formControl. Cuando lo pongo en la plantilla, funciona:

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

Pero el navegador me alerta:

Parece que está utilizando el atributo disabled con una directiva de formulario reactivo. Si establece disabled en true cuando configura este control en su clase de componente, el atributo disabled se establecerá en el DOM para usted. Recomendamos utilizar este enfoque para evitar errores de "cambio después de comprobar".

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

Así que lo puse en FormControl, y lo borré de la plantilla:

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

Pero no funciona (no está deshabilitando input). ¿Cuál es el problema?

FacundoGFlores
fuente
1
Esto parece funcionar bien con la versión actual de Angular 2: plnkr.co/edit/CQQtkYC9D5EoH0sAlNCV?p=preview
silentsod
Estoy usando el último proyecto de cli angular para probar
FacundoGFlores
2
Estás usando @ angular / material, por lo que, según sus problemas de github: github.com/angular/material2/issues/1171 Todavía no es compatible y están en alfa, por lo que no puedes esperar que tenga todas las funciones.
silentsod
Sí, era el problema
FacundoGFlores
6
Puedes intentar poner this.myForm.controls['id'].disable()en algún lugar del constructor. Hice una biblioteca que facilita el trabajo con formularios dinámicos: github.com/mat3e/dorf
mat3e

Respuestas:

116

Lo he estado usando [attr.disabled]porque todavía me gusta esta plantilla impulsada que la habilitación () / deshabilitación () programática ya que es superior en mi opinión.

Cambio

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

a

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

Si tiene un material más nuevo, cambie md-inputa mat-input.

bhantol
fuente
1
¡Funciona, gracias! Pero no entiendo por qué debería usar "attr.disabled" (no solo "disabled")?
Sergey Andreev
6
Solo para tener en cuenta, con [attr.disabled] no puede usar vincularlo de dos maneras. Solo funciona una vez. Con [disabled]y la advertencia en la consola está funcionando. Estoy usando Angular 4.1.3
The.Bear
2
Creo que eso [attr.disabled]simplemente no [disabled]
activa
3
¿Puede explicar por qué cree que es "superior"?
Lazar Ljubenović
1
Las propiedades del campo de formulario se pueden leer desde la plantilla HTML. Digamos que un buen día decide buscar lo que deshabilita un campo determinado, el instinto es caminar desde la plantilla HTML hacia el código mecanografiado en lugar de las otras formas.
bhantol
13

Puede habilitar / deshabilitar un control de formulario utilizando los siguientes métodos:

control.disable () o control.enable ()

Si eso no funcionó, puede usar una directiva

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

}

Entonces podrías usarlo así

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

Esta técnica se describe aquí:

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

Espero eso ayude

Kaloyan Stamatov
fuente
¿Puede mostrar algún fragmento de código js cómo hacer esto?
kumaresan_sd
proporcione muestras de stackb
kumaresan_sd
aquí hay un ejemplo: netbasal.com/…
Janatbek Sharsheyev
Eso no funciona con Angular 8. DaNgControl (`No provider for NgControl`)
pantonis
1
¡Puedo confirmar que esta solución ya no funciona a partir de Angular 8!
Martijn Hiemstra
10

Descubrí que necesitaba tener un valor predeterminado, incluso si era una cadena vacía para que funcionara. Así que esto:

this.registerForm('someName', {
  firstName: new FormControl({disabled: true}),
});

... tenía que convertirse en esto:

this.registerForm('someName', {
  firstName: new FormControl({value: '', disabled: true}),
});

Vea mi pregunta (que no creo que sea un duplicado): Pasar 'deshabilitado' en el objeto de estado de formulario al constructor FormControl no funciona

BBaysinger
fuente
9

En mi caso con Angular 8 . Quería activar / desactivar la entrada según la condición.

[attr.disabled] no funcionó para mí, así que aquí está mi solución.

Eliminé [attr.disabled]de HTML y en la función del componente realicé esta verificación:

if (condition) {
    this.form.controls.myField.disable();
} else {
    this.form.controls.myField.enable();
}
Anuj TBE
fuente
4

Inicialización (componente) usando:

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

Entonces, en lugar de usar (plantilla):

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

Simplemente elimine el atributo deshabilitado:

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

Y cuando tenga elementos para mostrar, inicie (en el componente): this.selector.enable();

Ignacio Ara
fuente
2

Solo para quienes están usando formularios reactivos: para elementos HTML nativos [attr.disabled] funcionará, pero para elementos materiales necesitamos deshabilitar dinámicamente el elemento.

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

De lo contrario, se mostrará en el mensaje de advertencia de la consola.

Tilak Bhandari
fuente
2

Probé estos en angular 7. Funcionó con éxito.

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

Por un formulario, el control hace deshabilitar

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

O método de configuración inicial.

first: new FormControl({disabled: true}, Validators.required)
Pu ChengLie
fuente
1

Use [attr.disabled] en lugar de [disabled], en mi caso funciona bien

Exari Constantin
fuente
2
Si bien esto puede ser posible, no debe utilizar una solución basada en plantillas cuando trabaje con formularios reactivos. El problema de mezclar esos dos es que ya no se puede confiar en el estado de forma reactiva.
enf0rcer
se usa para deshabilitar, pero si configuro esto como falso, también control para deshabilitar
kumaresan_sd
1

agregar disable = "true" al campo html Ejemplo: desactivar

<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
fuente
No funciona . enlace de muestra - stackblitz.com/edit/angular-zdpavf?file=src/app/…
kumaresan_sd
Esta respuesta no funcionará en forma reactiva. Esto está relacionado con el formulario basado en plantillas
Nambi N Rajan
1

La belleza de las formas reactivas es que puede detectar cambios de valores de cualquier elemento de entrada muy fácilmente y al mismo tiempo puede cambiar sus valores / estado. Así que esta es otra forma de abordar su problema usando enable disable.

Aquí está la solución completa en stackblitz .

Kedar9444
fuente
Le sugiero que publique el código aquí también, o al menos un fragmento. Encontré esta solución útil, por lo que suscribirse al cambio de valor y activar la activación / desactivación parece una buena opción.
John White
1

La desactivación de los campos de formulario de mat está exenta si está utilizando la validación de formulario, así que asegúrese de que su campo de formulario no tenga validaciones como (validators.required), esto funcionó para mí. por ejemplo:

editUserPhone: new FormControl ({valor: '', deshabilitado: verdadero})

esto hace que los números de teléfono del usuario no sean editables.

algo T
fuente
1

Esta fue mi solución:

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
fuente
1
Hola Frank, bienvenido a StackOverflow y gracias por tu respuesta. Si bien es ciertamente excelente proporcionar una solución funcional en código, puede ayudar a otros ahora y en el futuro a comprender mejor su respuesta si agrega un poco de explicación más allá del código.
robsiemb
1

en Angular-9 si desea deshabilitar / habilitar en el botón, haga clic aquí es una solución simple si está utilizando formas reactivas.

definir una función en el archivo component.ts

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

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

Llámelo desde su component.html

p.ej

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

Cuando cree un nuevo control de formulario, use el siguiente:

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

Si desea cambiar la actividad, use el siguiente:

this.variable.enable() 

o

this.variable.disable()
Aleksandr Zelenskiy
fuente
-1

agregue el atributo de nombre a su md-input. si no resuelve el problema, publique su plantilla

Taha Zgued
fuente
-4

La mejor forma de hacer esto.

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.
  })
}
usuario3345544
fuente