Formularze reaktywne - atrybut wyłączony

109

Próbuję użyć disabledatrybutu z pliku formControl. Kiedy wstawię to do szablonu, działa:

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

Ale przeglądarka ostrzega mnie:

Wygląda na to, że używasz atrybutu disabled z dyrektywą formularza reaktywnego. Jeśli ustawisz disabled na true podczas konfigurowania tej kontrolki w klasie komponentów, atrybut disabled zostanie faktycznie ustawiony w DOM za Ciebie. Zalecamy skorzystanie z tego podejścia, aby uniknąć błędów „zmieniono po sprawdzeniu”.

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

Więc umieściłem go w FormControl, i usunąłem z szablonu:

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

Ale to nie działa (nie wyłącza input). Jaki jest problem?

FacundoGFlores
źródło
1
Wydaje się, że działa to dobrze z aktualną wersją Angular 2: plnkr.co/edit/CQQtkYC9D5EoH0sAlNCV?p=preview
silentsod
Do testowania
używam
2
Używasz @ angular / material, więc zgodnie z ich wydaniami na githubie : github.com/angular/material2/issues/1171 To nie jest jeszcze obsługiwane i są w wersji alfa, więc nie możesz oczekiwać, że będzie kompletna.
cichy od
Tak, to był problem
FacundoGFlores
6
Możesz spróbować umieścić this.myForm.controls['id'].disable()gdzieś w konstruktorze. Zrobiłem bibliotekę, która ułatwia pracę z dynamicznymi formularzami: github.com/mat3e/dorf
mat3e

Odpowiedzi:

126

Używam, [attr.disabled]ponieważ nadal podoba mi się ten szablon oparty na programowym włączaniu () / wyłączaniu (), ponieważ jest lepszym IMO.

Zmiana

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

do

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

Jeśli korzystasz z nowszego materiału, zmień md-inputna mat-input.

bhantol
źródło
2
Działa, dzięki! Ale nie rozumiem, dlaczego powinienem używać „attr.disabled” (nie tylko „disabled”)?
Sergey Andreev
6
Zwróć uwagę, że z [attr.disabled] nie możesz użyć bind go na dwa sposoby. Działa tylko raz. Z [disabled]i ostrzeżenie w konsoli działa. Używam Angular 4.1.3
The.Bear
2
Myślę, że [attr.disabled]po prostu nie uruchamia ostrzeżenia, które [disabled]pokazuje
K1ngjulien_
4
Czy możesz wyjaśnić, dlaczego uważasz, że jest „lepszy”?
Lazar Ljubenović
1
Właściwości pola formularza można odczytać z szablonu HTML. Powiedzmy, że pewnego pięknego dnia zdecydujesz się sprawdzić, co wyłącza dane pole, a instynkt polega na przejściu od szablonu HTML do kodu maszynopisu niż na inne sposoby.
bhantol
15

Możesz włączyć / wyłączyć formant formularza przy użyciu następujących metod:

control.disable () lub control.enable ()

Jeśli to nie zadziałało, możesz użyć dyrektywy

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

}

Wtedy możesz tego użyć w ten sposób

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

Ta technika jest opisana tutaj:

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

Mam nadzieję, że to pomoże

Kaloyan Stamatov
źródło
czy możesz pokazać fragment kodu js, jak to zrobić
kumaresan_sd
proszę dostarczyć próbki
stackb
oto przykład: netbasal.com/…
Janatbek Sharsheyev
To nie działa z Angular 8. To dajeNgControl (`No provider for NgControl`)
pantonis
1
Mogę potwierdzić, że to rozwiązanie nie działa już od Angulara 8 !!
Martijn Hiemstra
13

W moim przypadku z Angular 8 . Chciałem włączyć / wyłączyć wejście w zależności od warunku.

[attr.disabled] nie działa dla mnie, więc oto moje rozwiązanie.

Usunąłem [attr.disabled]z HTML i w funkcji komponentu wykonałem tę kontrolę:

if (condition) {
    this.form.controls.myField.disable();
} else {
    this.form.controls.myField.enable();
}
Anuj TBE
źródło
12

Odkryłem, że potrzebuję wartości domyślnej, nawet jeśli był to pusty ciąg, aby działał. Więc to:

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

... musiał stać się tym:

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

Zobacz moje pytanie (które nie uważam za duplikat): Przekazywanie „wyłączone” w obiekcie stanu formularza do konstruktora FormControl nie działa

BBaysinger
źródło
4

Inicjalizacja (komponent) przy użyciu:

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

Wtedy zamiast używać (szablon):

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

Po prostu usuń atrybut wyłączony:

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

A kiedy masz elementy do pokazania, uruchom (w komponencie): this.selector.enable();

Ignacio Ara
źródło
3

Tylko ci, którzy używają formularzy reaktywnych: dla natywnych elementów HTML [attr.disabled] będzie działać, ale w przypadku elementów materialnych musimy dynamicznie wyłączyć element.

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

W przeciwnym razie pojawi się ostrzeżenie konsoli.

Tilak Bhandari
źródło
3

Wypróbowałem te w Angular 7. Udało się.

this.form.controls['fromField'].reset();
if(condition){
      this.form.controls['fromField'].enable();
}
else{
      this.form.controls['fromField'].disable();
}
Recep Duman
źródło
3
this.form.disable()
this.form.enable()

Dla jednego formcontrol wyłącza

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

Lub metoda początkowego zestawu.

first: new FormControl({disabled: true}, Validators.required)
Luis
źródło
1

Użyj [attr.disabled] zamiast [disabled], w moim przypadku działa dobrze

Exari Constantin
źródło
2
Chociaż może to być możliwe, nie należy używać rozwiązania opartego na szablonach podczas pracy z formularzami reaktywnymi. Problem z mieszaniem tych dwóch polega na tym, że nie można już ufać reaktywnemu stanowi formularza.
enf0rcer
używa do wyłączenia, ale jeśli
ustawię
1

dodaj disable = "true" do pola html Przykład: wyłącz

<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
źródło
Nie działa . przykładowy link - stackblitz.com/edit/angular-zdpavf?file=src/app/…
kumaresan_sd
Ta odpowiedź nie będzie działać w formie reavtive. Jest to związane z formularzem opartym na szablonie
Nambi N Rajan
1

Piękno formularzy reaktywnych polega na tym, że możesz bardzo łatwo wychwycić zmiany wartości dowolnego elementu wejściowego, a jednocześnie możesz zmienić ich wartości / status. Oto kolejny sposób rozwiązania problemu za pomocą enable disable.

Oto kompletne rozwiązanie na stackblitz .

Kedar9444
źródło
Proponuję zamieścić tutaj również kod lub przynajmniej fragment. Uważam, że to rozwiązanie jest przydatne, więc subskrybowanie zmiany wartości i wyzwalanie włączania / wyłączania wydaje się dobrą opcją.
John White
1

wyłączenie pól formularza mat jest wyłączone, jeśli używasz walidacji formularza, więc upewnij się, że twoje pole formularza nie ma żadnych walidacji, takich jak (validators.required), to zadziałało dla mnie. na przykład:

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

powoduje to, że numery telefonów użytkowników nie są edytowalne.

Somesh T
źródło
1

To było moje rozwiązanie:

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
źródło
1
Cześć Frank, witaj w StackOverflow i dziękuję za odpowiedź! Chociaż z pewnością wspaniale jest zapewnić działające rozwiązanie w kodzie, może pomóc innym teraz iw przyszłości lepiej zrozumieć twoją odpowiedź, jeśli dodasz trochę wyjaśnienia poza kodem.
robsiemb
1

w Angular-9, jeśli chcesz wyłączyć / włączyć na przycisku kliknij tutaj jest prostym rozwiązaniem, jeśli używasz formularzy reaktywnych.

zdefiniuj funkcję w pliku component.ts

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

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

Wywołaj to ze swojego component.html

na przykład

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

Kiedy tworzysz nową kontrolkę Form, użyj next:

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

Jeśli chcesz zmienić aktywność, użyj dalej:

this.variable.enable() 

lub

this.variable.disable()
Aleksandr Zelenskiy
źródło
-1

dodaj atrybut nazwy do swojego md-input. jeśli to nie rozwiąże problemu, prześlij swój szablon

Taha Zgued
źródło
-4

Najlepszy sposób na zrobienie tego.

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
źródło