Угловая наблюдаемая обновлена ​​слишком рано после добавления FormGroup - PullRequest
0 голосов
/ 02 декабря 2018

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

По сути, у меня есть FormArray из FormGroups, каждая из которых состоит из автозаполнения углового материала.Я хочу, чтобы параметры автозаполнения были Observable, чтобы я мог обновлять весь список параметров всякий раз, когда изменяется одна из групп FormGroups в массиве - в основном, когда выбран параметр, я не хочу, чтобы он был в состояниивыбранный любой другой группой FormGroup в массиве.

Но, и именно здесь будет светить мое новшество в angular, я обновляю список опций на valueChanges, но когда я нажимаю новыйFormGroup для массива, мне нужен тайм-аут, который запускает секунду valueChanges для того, чтобы параметры автозаполнения появлялись вообще.Если у меня его там нет, то список не отображается в последней добавленной группе FormGroup.

Почему это так?

Код здесь, на stackblitz

Просто нажмите Добавить ввод, и вы увидите список пользователей в автозаполнении, но если вы закомментируете строку 72 и нажмете Добавить ввод, вы не увидитесписок в последней добавленной группе форм.

РЕДАКТИРОВАТЬ

Будет гораздо проще увидеть вопрос, посмотрев код на stackblitz, но потому что я получилпредложили пересмотреть и закрыть, вот код компонента:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormControl, FormArray } from '@angular/forms';
import { switchMap } from 'rxjs/operators';
import { of } from 'rxjs'

const users = [
    {
        id:1,
        name:'user1',
    },
    {
        id:2,
        name:'user2',
    },
    {
        id:3,
        name:'user3',
    }
]

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  usersForm: FormArray;  
  users = users;
  filteredUsers: Observable<any>;
  selectedUsers = [];
  canAddInput = true;

  constructor(private fb: FormBuilder ) {}

  ngOnInit() {
    this.usersForm = this.fb.array([]);

    this
        .usersForm
        .valueChanges
        .subscribe(data => {
            this.selectedUsers = data.map(d => d.userNameSelector).filter(d => !!d);
            this.canAddInput = this.getUnselectedUsers().length !== 0 && this.usersForm.controls.length < this.users.length
        })

    //filtered users is an observable 
    this.filteredUsers = this
        .usersForm
        .valueChanges
        .pipe(
            switchMap(() => of(this.getUnselectedUsers()))
        )

   }

   getUnselectedUsers()
   {
    //console.log(this.users.filter(u => this._isNotSelectedUser(u.name)));
    return this.users.filter(u => this._isNotSelectedUser(u.name));
   }

  _isNotSelectedUser = user => !this.selectedUsers.includes(user)

  addInput() {
    this.usersForm.push(this.fb.group({userNameSelector:null}));

    //why do I need this - it triggers usersForm.valueChanges and filteredUsers is updated, but won't the code work without it why?
    setTimeout(() => this.usersForm.updateValueAndValidity(),1);
  }

  removeInput = idx => this.usersForm.removeAt(idx)

}

и HTML:

    <form class="example-form" [formGroup]='usersForm'>
  <div *ngIf="usersForm.controls">
    <div
      *ngFor="let ctrlName of usersForm.controls; let i = index;" [formGroupName]="i">

      <mat-form-field class="example-full-width">
        <input 
          matInput 
          placeholder="Choose a user" 
          [matAutocomplete]="auto"
          formControlName="userNameSelector"
        >
      </mat-form-field>
      <!-- <span>Your choice is: {{usersForm.get(input.name).value | json}}</span> -->

      <mat-autocomplete #auto="matAutocomplete">
          <mat-option 
            <!-- this async pipe is going to be important here -->
            *ngFor="let user of filteredUsers | async" 
            [value]="user.name"
          >
            <span>{{ user.name }}</span>
          </mat-option>
      </mat-autocomplete>
      <button 
        mat-raised-button 
        color="warn"
        (click)="removeInput(i)"
      >Remove Input</button>
    </div>
  </div>
  <button 
    *ngIf="canAddInput"
    mat-raised-button color="primary"
    (click)="addInput()"
  >Add Input</button>
</form>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...