Angular 4 - Reactive Forms включить / отключить не работает - PullRequest
0 голосов
/ 26 апреля 2018

У меня проблемы с включением и отключением элементов управления формой в моем приложении. Вероятно, это связано с тем, что форма включается / отключается в асинхронном контексте.

Вот как выглядит код.

user.component.html

<form [formGroup]="form">
    <input type="text" id="name" formControlName="name" />
    <input type="text" id="age" formControlName="age" />
</form>

user.component.ts

ngOnInit() {

     this._route.queryParams.subscribe(params => {
            getUser(params.userId).subscribe(user => {
                 this._buildForm(user);
            })
     });
}

private _buildForm(user){
    this.form = _fb.group({
        name: [{value: user.name, disabled: user.someCondition}, Validators.required],
        age: [{value: user.age, disabled: user.anotherCondition}, Validators.required]
    })
}    

Когда пользователь впервые загружается при изменении параметра, элементы управления включаются / отключаются в зависимости от их соответствующих условий. При последующем изменении параметров состояние элементов управления остается прежним, хотя значения установлены соответствующим образом.

Я пробовал разные способы исправить это, но без помощи. Например, я попробовал следующее в конце метода _buildForm.

this.form.disable() //Doesn't do anything

this.form.controls.name.disable(); //Doesn't help

Одна вещь, которая работает как положено, заключается в следующем (но это не то, что требуется).

<button (click)="form.disable()" value="Disable Form" />
<button (click)="form.enable()" value="Enable Form" />

Мне кажется, что проблема в том, что _buildForm() вызывается из асинхронного контекста (метод подписки).

Как я могу исправить эту проблему?

UPDATE

Обратите внимание, что подписка Observable запускается на основе навигации, как показано ниже.

this._router.navigate([], {
   relativeTo: this._route,
   queryParams: {userId: 10}
})

ОБНОВЛЕНИЕ 2 https://angular -cvf1fp.stackblitz.io

Это более простой способ понять мою проблему

Ответы [ 4 ]

0 голосов
/ 26 апреля 2018
  • Создайте formGroup непосредственно в ngOnit с отключенными по умолчанию элементами управления, поэтому вы уверены, что оно существует без беспокойства по поводу асинхронных проблем.
  • В this._route.queryParams.subscribe(...) вы можете использовать this.form.setValue({//set all control values}) или this.form.patchValue({//set individual controls}) для обновления отдельных элементов управления по мере необходимости / после их появления.
  • Используйте переменные экземпляра компонента для condition и someOtherCondition (или user объекта в целом, если вы хотите отделить вашу модель данных от модели формы - они не обязательно должны быть одинаковыми). Инициализируйте их как «ложные», и вместо этого обращайтесь к ним для включения / выключения элементов управления в создании formGroup. Вы также можете обновить эти переменные в том же блоке .subscribe(), как только пользовательские данные будут на месте, вместо ожидания прямого доступа к модели данных user.

Таким образом, ваши элементы управления и formGroup существуют и отключаются, пока не будут доступны асинхронные данные.

0 голосов
/ 26 апреля 2018

Вам просто нужно включить / отключить методы управления формой.

Вот стекаблиц пример . Работает отлично.

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  group;
  isDisabled = true;

  constructor(fb: FormBuilder) {
    this.group = fb.group({
      stuff: fb.control({value: 'stuff', disabled: this.isDisabled})
    });
  }

  toggle() {
    this.isDisabled = !this.isDisabled;

    this.group.controls.stuff[this.isDisabled ? 'enable' : 'disable']();
  }
}
0 голосов
/ 26 апреля 2018
<form [formGroup]="form">
    <input type="text" id="name" fromControlName="name" />
    <input type="text" id="age" fromControlName="age" />
</form>

вы видите здесь опечатку? fromControlName должно быть formControlName После этого переключения будет работать;)

https://angular -rivxs5.stackblitz.io

0 голосов
/ 26 апреля 2018

Ты прав. Подписка активируется только один раз, поэтому после отправки формы пользовательский объект больше не меняется. Для этого добавьте, например, обработчик событий в форму отправки.

user.component.html

<form [formGroup]="form" (submit)="_updateForm()">
    <input type="text" id="name" fromControlName="name" />
    <input type="text" id="age" fromControlName="age" />
</form>

user.component.ts

private userId: any;


ngOnInit() {
    this._route.queryParams.subscribe(params => {
        this.userId = params.userId;
        this._updateForm();
    });
}

private _buildForm(user){
    this.form = _fb.group({
        name: [{value: user.name, disabled: user.someCondition}, Validators.required],
        age: [{value: user.age, disabled: user.anotherCondition}, Validators.required]
    });
} 

// The update function has to be public to be called inside your template
public _updateForm(){
    getUser(this.userId).subscribe(user => {
        this._buildForm(user);
    });
}    
...