Данные из селектора, чтобы замедлить для FormBuilder - PullRequest
0 голосов
/ 29 апреля 2020

Я хочу иметь возможность редактировать существующие данные из базы данных в реактивной форме. Я использую селектор, чтобы получить данные из хранилища (Ngrx), но проблема в том, что компонент отображает форму, даже если данные еще не были загружены.

Я боролся с этим, данные отображаются, если я делаю тайм-аут перед вызовом 'createEditForm', но все вылетает в фоновом режиме, потому что в начале нет данных ..

Есть Есть хорошее решение, чтобы пропустить рендеринг формы до тех пор, пока переменная ev $ не будет 'undefiened' ...

. Сообщение об ошибке прямо сейчас: 'EventEditComponent. html: 2 ОШИБКА Ошибка: formGroup ожидает экземпляр FormGroup. Пожалуйста, введите один. '

И много ' TypeError: Невозможно прочитать свойство 'invalid' из undefined в Object.eval [as updateDirectives] (EventEditComponent. html: 10)

    @Component({
      selector: 'ex-event-edit',
      templateUrl: './event-edit.component.html',
      changeDetection: ChangeDetectionStrategy.OnPush,
      styleUrls: ['./event-edit.component.scss'],
    })
    export class EventEditComponent implements OnInit {
      ev$: Observable<Event>;
      eventEditForm: FormGroup;
      eventId: number;
      starttime: Date;
      endtime: Date;
      fileUpload: File = null;
      imageUrl: string;

      constructor(
        private store$: Store<AppState>,
        private fb: FormBuilder,
        private dateAdapter: DateAdapter<Date>,
        private activatedRoute: ActivatedRoute,
        private actionsSubject$: ActionsSubject
      ) {
        dateAdapter.setLocale('sv');
      }

      ngOnInit() {
        this.activatedRoute.params.subscribe((params) => {
          this.eventId = params['id'];
        });

        this.store$.dispatch(new fromEvents.LoadEvent(+this.eventId)); //Load specific event to the state
        this.ev$ = this.store$.pipe(select(fromEvents.getCurrentEvent)); //Get the specific event

        setTimeout(() => { //Bad solution, but the only way to display the data in the component....
          this.createEventEditForm();
        }, 300);
      }

      createEventEditForm() {
        this.ev$.subscribe((ev) => {
          this.eventEditForm = this.fb.group(
            {
              id: [ev.id],
              title: [ev.title, Validators.required],
              description: [ev.description, Validators.required],
              image: [null],
              location: [ev.location, Validators.required],
              startdate: [new Date(ev.startDate), Validators.required],
              enddate: [new Date(ev.endDate), Validators.required],
            },
            { validator: this.DateValidation }
          );
          this.starttime = ev.startDate;
          this.endtime = ev.endDate;
          this.eventId = ev.id;
          this.imageUrl = ev.image;
        });
      }

- HTML -

    <form *ngIf="ev$; else stillLoading" [formGroup]="eventEditForm" (ngSubmit)="updateEvent()" >
      <button [disabled]="!eventEditForm.dirty || !eventEditForm.valid" type="submit" class="btn btn- 
      success">Save changes</button>
      <div class="row">
      <div class="title">
        <mat-form-field appearance="outline">
          <mat-label>Change title</mat-label>
          <mat-error *ngIf="eventEditForm.invalid">{{ getErrorMessage('title') }}</mat-error>
          <input class="title" type="text" matInput formControlName="title" autocomplete="off"  />
        </mat-form-field>
      </div>
      </div>

    ....more code but it's similar to the code above
    </form>

    <ng-template #stillLoading>
      <p>Loading...</p>
    </ng-template>

1 Ответ

0 голосов
/ 05 мая 2020

Проблема в том, что реактивные формы работают мгновенно, когда ngrx является асинхронным. Чтобы решить эту проблему, вам нужно разделить ваш код на два компонента: умный и немой.

У тупого должен быть форма и @Input для данных формы (объект, а не наблюдаемый). Вы можете реализовать интерфейс OnChange для обновления состояния формы на основе нового входного значения.

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

<form-component [data]="ev$ | async"></form-component>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...