javascript 无法使用writeValue angular函数读取undefined的属性(阅读“nativeElement”)

t40tm48m  于 2023-05-16  发布在  Java
关注(0)|答案(1)|浏览(235)

我正在开发一个Angular 应用程序,它有一个带有我需要遵循的预定义类的体系结构。我显示了一个地址列表,并添加了CRUD功能。
我遇到的问题是在编辑地址时。填充下拉列表的数据通过对.Net核心后端的API调用来获得。我认为我遇到的问题是在数据从后端到达之前访问数据/属性。问题是,当得到错误时,包含国家和城市的下拉列表会被填充,但正确的值(正在编辑的记录的国家和城市)不会自动选择。
单击“编辑”按钮后出现此错误。有趣的是,当编辑窗口已经打开,我再次点击编辑,所有的工作正常,没有错误。正确的值也是从下拉列表中选择的。
错误:

TypeError: Cannot read properties of undefined (reading 'nativeElement')
    at push.wnGv.SelectComponent.writeValue (select.component.ts:42:6)
    at shared.ts:122:24
    at model.ts:1188:25
    at Array.forEach (<anonymous>)
    at FormControl.setValue (model.ts:1187:22)
    at model.ts:1520:27
    at Array.forEach (<anonymous>)
    at FormGroup.setValue (model.ts:1518:24)
    at NgForm.setValue (ng_form.ts:283:18)
    at eloket-form.ts:10:5

Angular代码:adres-form.component.ts:

export interface FlowbackPersoneelslidAdresForm {

  straatLijn: string;
  straatLijn2: string;
  nummer: number;
  bus: number;
  codeGemeente: CodeGemeente;
  codeAdresType: CodeAdrestype;
  codeLand: CodeLand;
  //isPrive: boolean;
  isCorrespondentie: boolean;
  beginDatum: moment.Moment;
  eindDatum: moment.Moment;
  attest: any;
}

@Component({
  selector: 'app-adres-form',
  templateUrl: './adres-form.component.html',
  styleUrls: ['./adres-form.component.scss']
})

export class AdresFormComponent implements OnInit {

  @ViewChild('f', { static: true }) FlowbackPersoneelslidAdresForm: EloketForm<FlowbackPersoneelslidAdresForm>;

  @Input() serverValidationError: ValidationBag;

  @Input() submitButtonText: string;

  @Input() set flowBackPersoneelslidAdres(value: FlowbackPersoneelslidAdres) {
    if (!value) {
      return;
    }
    console.log('before setFormValue, value passed to setFormValue:', value);
    console.log(value.codeAdresType);
    setFormValue(this.FlowbackPersoneelslidAdresForm, {
      straatLijn: value.straat,
      straatLijn2: value.straatLijn2,
      nummer: value.huisNummer,
      bus: value.busNummer,
      codeAdresType: value.codeAdresType,
      codeGemeente: value.codeGemeente,
      codeLand: value.codeLand,
      beginDatum: moment(value.beginDatum),
      eindDatum: moment(value.eindDatum),
      isCorrespondentie: value.isCorrespondentie,
      //isPrive: value.isPrive,
      attest: value.flowbackPersoneelslidAdresAttest
    });
    if (value.flowbackPersoneelslidAdresAttest) {
      this.attestAanwezig = true;
      this.attest = new FlowbackPersoneelslidAdresAttest(value.flowbackPersoneelslidAdresAttest);
    }
  }

  @Output() public flowbackPersoneelslidAdresChange = new EventEmitter<FlowbackPersoneelslidAdresForm>();

  //defaults to current date
  minDateActiefVanaf: moment.Moment = moment(new Date());
  codeAdrestypeSelectConfig: ModelSelectConfig<CodeAdrestype>;
  codeAdrestypes: CodeAdrestype[];

  codeGemeenteSelectConfig: ModelSelectConfig<CodeGemeente>;
  codeGemeenten: CodeGemeente[];

  codeLandSelectConfig: ModelSelectConfig<CodeLand>;
  codeLanden: CodeLand[];

  fileToUpload: File = null;
  attestAanwezig: boolean = false;
  attest: FlowbackPersoneelslidAdresAttest;
  loaded: boolean = false;

  constructor(private confirmationService: ConfirmationService, private codeTabelService: CodeTabelService) {
    this.loadCodeAdrestypes();
    this.loadCodeGemeenten();
    this.loadCodeLanden();
    console.log('min actief vanaf', this.minDateActiefVanaf);
  }

  /*
  ngAfterViewInit(): void {
    this.loadCodeAdrestypes();
    this.loadCodeGemeenten();
    this.loadCodeLanden();
  }
  */

  ngOnInit(): void {
  }

  public async handleFileInput(files: FileList) {
    this.fileToUpload = files.item(0);
  }

  savePersoneelslidAdres({ valid, value }: EloketForm<FlowbackPersoneelslidAdresForm>) {
    if (valid) {
      console.log("savePersoneelslidAdres", value);
      value.attest = this.fileToUpload;
      this.flowbackPersoneelslidAdresChange.emit(value);
    }
  }

  async HaalAttest(id: number) {
    //todo: implement
    //let bewijs = await this.flowbackService.GetFlowbackPersoneelslidAdresAttest(id).toPromise();
    let bewijs = null;
    let blob = convertByteArrayToBlob(bewijs.data.content, bewijs.data.contentType);
    FileSaver.saveAs(blob, bewijs.data.fileName.substr(9));

  }

  async DeleteAttest(id: number) {
    const confirmed = await this.confirmationService.promptConfirm('Personalia.Bank.VerwijderenAttestConfirm');
    if (confirmed) {
      //todo: implement
      //var deleted = await this.flowbackService.DeleteFlowbackPersoneelslidAdresAttest(id).toPromise();
      var deleted = true;
      if (deleted) {
        this.attestAanwezig = false;
      }
    }
  }

  async loadCodeAdrestypes() {
    this.codeAdrestypes = [];
    const codeAdrestypeDto = await this.codeTabelService.GetCodeAdrestypes().toPromise();
    this.codeAdrestypes = codeAdrestypeDto.map(item => new CodeAdrestype(item))
                                          .sort((a, b) => (b.omschrijving < a.omschrijving ? 1 : -1));

    this.codeAdrestypeSelectConfig = new ModelSelectConfig(this.codeAdrestypes,
                                                          codeAdrestype => codeAdrestype.codeAdrestypeId.toString(), 
                                                          codeAdrestype => codeAdrestype.omschrijving);
  }

  async loadCodeGemeenten() {
    this.codeGemeenten = [];
    const codeGemeenteDto = await this.codeTabelService.GetCodeGemeentes().toPromise();
    this.codeGemeenten = codeGemeenteDto.map(item => new CodeGemeente(item))
                                        .sort((a, b) => (b.postNrGemeente < a.postNrGemeente ? 1 : -1));

    this.codeGemeenteSelectConfig = new ModelSelectConfig(this.codeGemeenten,
                                                          codeGemeente => codeGemeente.codeGemeenteId.toString(), 
                                                          codeGemeente => codeGemeente.postNrGemeente.toString() + ' ' + codeGemeente.gemeente);

    this.loaded = true;
  }

  async loadCodeLanden() {
    this.codeLanden = [];
    const codeLandDto = await this.codeTabelService.GetCodeLanden().toPromise();
    this.codeLanden = codeLandDto.map(item => new CodeLand(item))
                                          .sort((a, b) => (b.naam < a.naam ? 1 : -1));

    this.codeLandSelectConfig = new ModelSelectConfig(this.codeLanden,
                                                        codeLand => codeLand.codeLandId.toString(), 
                                                        codeLand => codeLand.naam);
  }
}

adres-form-component.html:

<form #f="ngForm" (ngSubmit)="savePersoneelslidAdres(f)">
    <div class="form-group row mb-3">
        <label class="col-4 col-form-label">van</label>
        <div class="col-8">
            <app-date-picker name="beginDatum" [minDate]="minDateActiefVanaf" ngModel></app-date-picker>
        </div>
    </div>

    <div class="form-group row mb-3">
        <label class="col-4 col-form-label">tot</label>
        <div class="col-8">
          <app-date-picker name="eindDatum" [minDate]="minDateActiefVanaf" ngModel></app-date-picker>
        </div>
    </div>

    <div class="form-group row mb-3">
        <label class="col-4 col-form-label">adrestype</label>
        <div class="col-8">
            <app-select name="codeAdresType" [selectConfig]="codeAdrestypeSelectConfig" ngModel>
            </app-select>
        </div>
    </div>

    <div class="form-group row mb-3">
      <label class="col-4 col-form-label">Straatlijn</label>
      <div class="col-8">
        <input class="form-control" type="text" name="straatLijn" ngModel>
      </div>
    </div>

    <div class="form-group row mb-3">
        <label class="col-4 col-form-label">Straatlijn2</label>
        <div class="col-8">
          <input class="form-control" type="text" name="straatLijn2" ngModel>
        </div>
    </div>

    <div class="form-group row mb-3">
        <label class="col-4 col-form-label">Nummer</label>
        <div class="col-8">
          <input class="form-control" type="text" name="nummer" ngModel>
        </div>
    </div>

    <div class="form-group row mb-3">
        <label class="col-4 col-form-label">Bus</label>
        <div class="col-8">
          <input class="form-control" type="text" name="bus" ngModel>
        </div>
    </div>

    <div class="form-group row mb-3">
      <label class="col-4 col-form-label">Gemeente</label>
      <div class="col-8">
        <app-select name="codeGemeente" [selectConfig]="codeGemeenteSelectConfig" ngModel></app-select>
      </div>
    </div>

    <div class="form-group row mb-3">
        <label class="col-4 col-form-label">Land</label>
        <div class="col-8">
            <app-select name="codeLand" [selectConfig]="codeLandSelectConfig" ngModel></app-select>
        </div>
    </div>

    <div class="form-group row mb-3">
        <label class="col-4 col-form-label">Gebruiken als correspondentieadres?</label>
        <div class="col-8">
            <input type="checkbox" name="isCorrespondentie" ngModel>
            <label>Correspondentie</label>
        </div>
    </div>

    <div class="form-group row mb-3">
      <label translate="Personalia.Bank.Bewijs" class="col-4 col-form-label"></label>
      <div class="col-8">
        <ng-container *ngIf="attestAanwezig">
          <label>{{attest.naam}}</label>&nbsp;
          <button (click)="HaalAttest(attest.id)" class="btn btn-sm btn-light"><i class="far fa-file-pdf fa-2x"></i></button>&nbsp;&nbsp;
          <button (click)="DeleteAttest(attest.id)" class="btn btn-sm btn-light"><i class="fal fa-trash-alt fa-2x"></i></button>
        </ng-container>
        <ng-container *ngIf="!attestAanwezig">
          <input type="file" id="file" (change)="handleFileInput($event.target.files)">
        </ng-container>
        
      </div>
    </div>

    <div class="row">
      <div class="col-12">
        <button class="btn btn-dark float-right" type="submit" [translate]="submitButtonText"></button>
      </div>
    </div>
    <app-global-form-error [error]="serverValidationError" [possibleErrors]="['AfwezigheidtypeYearsIncorrectOrder']"></app-global-form-error>
  </form>

wijzig-adres.component.html(编辑地址):

<h2>Adres wijzigen</h2>
<app-adres-form *ngIf="wijzigFlowbackPersoneelslidAdres && wijzigFlowbackPersoneelslidAdres.codeGemeenteId != null" submitButtonText="Button.Edit" [serverValidationError]="serverValidationError" [flowBackPersoneelslidAdres]="wijzigFlowbackPersoneelslidAdres" (flowbackPersoneelslidAdresChange)="onWijzigFlowbackPersoneelslidAdres($event)"></app-adres-form>

wijzig-adres.component.ts:

@Component({
  selector: 'app-wijzig-adres',
  templateUrl: './wijzig-adres.component.html',
  styleUrls: ['./wijzig-adres.component.scss']
})
export class WijzigAdresComponent implements OnInit {

  wijzigFlowbackPersoneelslidAdres: WijzigFlowbackPersoneelslidAdres;
  serverValidationError: ApiError;
  id: number;

  constructor(private flowbackService: FlowbackService, private notificationService: NotificationService,
    private router: Router, private route: ActivatedRoute, private routeParamsChange: RouteParamsChange) {
    this.routeParamsChange.watch(this.route, (params) => {
      this.id = params.id;
      this.loadData();
    });
  }

  ngOnInit(): void {
  }

  async loadData() {
    const flowbackPersoneelslidAdres = await this.flowbackService.GetFlowbackPersoneelslidAdresById(this.id).toPromise();
    this.wijzigFlowbackPersoneelslidAdres = new WijzigFlowbackPersoneelslidAdres(flowbackPersoneelslidAdres.data);

    console.log('load data in wijzig-adres component:', this.wijzigFlowbackPersoneelslidAdres);
  }

  async onWijzigFlowbackPersoneelslidAdres(flowback: FlowbackPersoneelslidAdresForm) {

    CatchFormError(this, async () => {

      const updateAdres: WijzigFlowbackPersoneelslidAdres = {
        id: this.id,
        straat: flowback.straatLijn,
        straatLijn2: flowback.straatLijn2,
        huisNummer: flowback.nummer,
        busNummer: flowback.bus,
        codeAdrestypeId: flowback.codeAdresType.codeAdrestypeId,
        codeGemeenteId: flowback.codeGemeente.codeGemeenteId,
        codeLandId: flowback.codeLand.codeLandId,
        beginDatum: flowback.beginDatum.format('MM/DD/YYYY'),
        eindDatum: flowback.eindDatum.format('MM/DD/YYYY'),
        isPrive: false,
        isCorrespondentie: flowback.isCorrespondentie
      };

      let objJsonStr = JSON.stringify(updateAdres);
      let objJsonB64 = Buffer.from(objJsonStr).toString("base64");

      await this.flowbackService.UpdateFlowbackPersoneelslidAdres({ flowback: objJsonB64, file: flowback.attest as any }).toPromise();
      this.notificationService.showMessage('Personalia.Bank.RekeningNummerGewijzigd');
      await this.router.navigate(['../../'], { relativeTo: this.route });
    });
  }

}

adres-overzicht.component.html(地址概述)

<app-master-detail [route]="route">
    <app-master>
      <div class="page">
        <div class="header">
            <h3>ADRESSEN</h3>
        </div>
        <div class="content">
          <div class="row">
            <div class="col-12">
              <div class="onderdeel-adres" *ngFor="let adres of Adressen; let i = index;">
                <table>
                  <tr>
                    <td colspan="2">
                      <h3>{{adres.adresType}}</h3>
                    </td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="Personalia.Adres.Van"></label></td>
                    <td class="inhoud">{{adres.beginDatum|date:'dd/MM/yyyy'}}</td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="Personalia.Adres.Tot"></label></td>
                    <td class="inhoud">
                      <ng-container *ngIf="!adres.eindDatum.startsWith('2999')">{{adres.eindDatum|date:'dd/MM/yyyy'}}</ng-container>
                      <ng-container *ngIf="adres.eindDatum.startsWith('2999')"><span translate="Personalia.Adres.Onbepaald"></span></ng-container>
                    </td>
                  </tr>
                  <tr>
                    <td colspan="2">&nbsp;</td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="Personalia.Adres.Straat"></label></td>
                    <td class="inhoud">{{adres.straat}}</td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="Personalia.Adres.Nr"></label></td>
                    <td class="inhoud">{{adres.huisnummer}}</td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="Personalia.Adres.Bus"></label></td>
                    <td class="inhoud">{{adres.busnummer}}</td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="Personalia.Adres.PostcodeGemeente"></label></td>
                    <td class="inhoud">{{adres.codeGemeente.postnrDeelGemeente}} {{adres.codeGemeente.deelGemeente}}</td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="Personalia.Adres.Land"></label></td>
                    <td class="inhoud">{{adres.codeLand.naam}}</td>
                  </tr>
                  <tr>
                    <td colspan="2" class="inhoudCorAdres">&nbsp;<span *ngIf="adres.isCorrespondentie" translate="Personalia.Adres.Correspondentie"></span></td>
                  </tr>
                </table>                      
              </div>
              
              <ng-container *ngIf="flowBackAdresGegevens && flowBackAdresGegevens.length > 0">
                <div [ngClass]="{'onderdeel-flowback-adres':flowback.toestand !== 30, 'onderdeel-error-flowback-adres':flowback.toestand === 30}" *ngFor="let flowback of flowBackAdresGegevens; let i = index;">
                  <table>
                  <tr>
                    <td class="label"><label translate="">adrestype</label></td>
                    <td class="inhoud">{{ flowback.codeAdresType.omschrijving }}</td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="Personalia.Adres.Van"></label></td>
                    <td class="inhoud">{{ flowback.beginDatum | date:'dd/MM/yyyy' }}</td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="Personalia.Adres.Tot"></label></td>
                    <td class="inhoud">
                      <ng-container *ngIf="!flowback.eindDatum.startsWith('2999')">{{ flowback.eindDatum | date:'dd/MM/yyyy' }}</ng-container>
                      <ng-container *ngIf="flowback.eindDatum.startsWith('2999')"><span translate="Personalia.Adres.Onbepaald"></span></ng-container>
                    </td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="Personalia.Adres.Straat"></label></td>
                    <td class="inhoud">{{ flowback.straat }} {{ flowback.straatLijn2 }}</td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="Personalia.Adres.Nr"></label></td>
                    <td class="inhoud">{{ flowback.huisNummer }}</td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="Personalia.Adres.Bus"></label></td>
                    <td class="inhoud">{{ flowback.busNummer }}</td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="Personalia.Adres.PostcodeGemeente"></label></td>
                    <td class="inhoud">{{ flowback.codeGemeente.postnrDeelGemeente }} {{ flowback.codeGemeente.deelGemeente }}</td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="Personalia.Adres.Land"></label></td>
                    <td class="inhoud">{{ flowback.codeLand.naam }}</td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="">iscorrespondentie</label></td>
                    <td class="inhoud"><input type="checkbox" [checked]="flowback.isCorrespondentie" disabled="true"/></td>
                  </tr>
                  <tr>
                    <td class="label"><label translate="">opmerking</label></td>
                    <td class="inhoud">{{ flowback.flowbackOpmerking }}</td>
                  </tr>
                  <!-- todo: only show opmerking when toestand = 30 (geweigerd?) -->
                  <tr *ngIf="flowback.toestand === 30">
                    <td class="label"><label translate="Personalia.Bank.Opmerking"></label></td>
                    <td class="inhoud">{{ flowback.flowbackOpmerking }}</td>
                  </tr>
                  <ng-container *ngIf="flowback.toestand !== 20">
                    <tr>
                      <td colspan="2" style="text-align: center;">
                        <button class="btn btn-sm btn-light" (click)="OnEdit(flowback)"><i class="fal fa-edit fa-2x"></i></button>&nbsp;
                        <button class="btn btn-sm btn-light" (click)="onDelete(flowback)"><i class="fal fa-trash-alt fa-2x"></i></button>
                      </td>
                    </tr>
                  </ng-container>
                </table>
              </div>
            </ng-container>
            <!-- make sure the data arrived from the api before accessing it -->
            <ng-container *ngIf="Adressen && Adressen.length > 0">
              <div class="onderdeel-toevoegen">
                <table>
                  <tr>
                    <td colspan="2">
                      <h3><label translate="Personalia.Adres.Nieuw"></label></h3>
                    </td>
                  </tr>
                  <tr>
                    <td>
                      <app-date-picker [(ngModel)]="datumVanaf" [minDate]="datumVanaf"></app-date-picker>
                    </td>
                    <td>
                      <button [routerLink]="['nieuw', datumVanaf.format('MM/DD/YYYY'), Adressen[0].personeelslidId]"
                        translate="Personalia.Adres.Toevoegen" class="btn btn-dark"></button>
                    </td>
                  </tr>
                </table>
              </div>
            </ng-container>

              <div class="onderdeel-waarschuwing">
                <label>Gegevens niet correct ?<br/><br/>Contacteer uw personeelsadviseur of dossierbeheerder</label>
              </div>
            </div>

          </div>
        </div>
      </div>
    </app-master>
    <app-detail>
      <router-outlet></router-outlet>
    </app-detail>
</app-master-detail>

adres-overzicht.component.ts:

@Component({
  selector: 'app-adres-overzicht',
  templateUrl: './adres-overzicht.component.html',
  styleUrls: ['./adres-overzicht.component.scss'],
  providers: [ChildRouteChanges, RouteParamsChange]
})
export class AdresOverzichtComponent implements OnInit {

  public Adressen: PersoneelslidAdres[];
  public datumVanaf: Moment;
  public flowBackAdresGegevens: FlowbackPersoneelslidAdres[];

  constructor(public route: ActivatedRoute, childRouteChanges: ChildRouteChanges, public router: Router,
    public personeelslidservice: PersoneelslidService, public flowbackService: FlowbackService,
    public confirmationService: ConfirmationService, public notificationService: NotificationService) { 
    this.datumVanaf = moment().add(1, 'M').startOf('month');

    childRouteChanges.watch(router, route, () => {
      this.loadPersoneelslidAdressen();
    });
  }

  ngOnInit(): void {
    this.loadPersoneelslidAdressen();
  }

  async loadPersoneelslidAdressen() {
    let personeelslidAdresDto = await this.personeelslidservice.GetPersoneelslidAdres().toPromise();
    this.Adressen = personeelslidAdresDto.data;

    let flowbackPersoneelslidAdresDto = await this.flowbackService.GetFlowbackPersoneelslidAdres().toPromise();
    this.flowBackAdresGegevens = flowbackPersoneelslidAdresDto.data;
  }

  async OnEdit(flowback: FlowbackPersoneelslidAdres) {
    const id = flowback.id;
    console.log('id', flowback.id);
    this.router.navigate(['wijzig', id], { relativeTo: this.route });
  }

  async onDelete(flowback: FlowbackPersoneelslidAdres) {
    try { 
      const confirmed = await this.confirmationService.promptConfirm('Personalia.Adres.Flowback.VerwijderenConfirm', { beginDatum: apiStringToDate(flowback.beginDatum).format('DD/MM/YYYY')});
      if (confirmed) {
        await this.flowbackService.VerwijderFlowbackPersoneelslidAdres(flowback.id).toPromise();
        this.loadPersoneelslidAdressen();
      }
    } catch (e) {
      const { error } = e as ErrorEloket;

      if (!error.validationResult.isValid) {

        for (const err of error.validationResult.errors) {
          this.notificationService.showMessage(`Validatie.${ValidationError[err.error]}`, err.parameters);
        }
      }
    }

  }

}

model-select-config.ts:

import { Option } from './option';
import { SelectConfig } from './select-config';

export class ModelSelectConfig<T> implements SelectConfig<T> {
  public selectOptions: Option[];
  public options: T[];
  constructor(items: T[], public keySelector: (t: T) => string, textSelector: (t: T) => string) {
    this.options = items;
    this.selectOptions = items?.map(i => new Option(keySelector(i), textSelector(i)));
  }
}

select.component.ts:

import { Component, Input, forwardRef, ViewChild, ElementRef, HostBinding } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { SelectConfig } from './select-config';

@Component({
  selector: 'app-select',
  templateUrl: './select.component.html',
  styleUrls: ['./select.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => SelectComponent),
      multi: true
    }
  ]
})
export class SelectComponent<T> implements ControlValueAccessor {
  @ViewChild('select') select: ElementRef<HTMLSelectElement>;

  @Input() selectConfig: SelectConfig<T>;
  @HostBinding('class.read-only') @Input() readOnly: boolean;

  @Input() emptyTranslationKey: string;
  @Input() defaultValue: string;

  private onChange = (_: T) => { };
  public onTouched = () => { };

  constructor() {
 }

  selectedChange(key: string) {
    const { keySelector: keyFor } = this.selectConfig;
    const option = this.selectConfig.options.find(o => keyFor(o) === key);
    this.onChange(option);
  }

  writeValue(obj: T): void {
    if (!obj) { return; }
     //this fixes the issue
     /*
     setTimeout(() => {
      this.select.nativeElement.value = this.selectConfig.keySelector(obj);
    }, 100);
    */
    this.select.nativeElement.value = this.selectConfig.keySelector(obj);
  }

  registerOnChange(fn: (option: T) => void): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: () => void): void {
    this.onTouched = fn;
  }

  setDisabledState?(isDisabled: boolean): void {
    this.readOnly = isDisabled;
  }

  toggleSelect() {
    this.select.nativeElement.click();
  }
  
}

select.component.html:

<select class="form-control" #select (change)="selectedChange($event.target.value)"
  *ngIf="selectConfig" [disabled]="readOnly" [value]="defaultValue">
  <option disabled selected *ngIf="emptyTranslationKey" [value]="null" [translate]="emptyTranslationKey"></option>
  <option *ngFor="let option of selectConfig.selectOptions" [value]="option.key" [translate]="option.text"></option>
</select>

注意我在select.component.ts的注解中添加的行修复了这个问题。然而,这不是一个可接受的解决方案,因为编辑这个文件是最后一次去+这将延迟所有使用它的代码。
任何人都有一个想法,我可以做什么,以使这一工作正确?

wz3gfoph

wz3gfoph1#

解决方案是添加一个初始值为false的Subject,从API加载数据后设置为true。只有这样,表单数据才会被设置,触发在正确的时间填充选择。

export interface FlowbackPersoneelslidAdresForm {

  straat: string;
  straatLijn2: string;
  huisNummer: number;
  busNummer: number;
  codeGemeente: CodeGemeente;
  codeAdresType: CodeAdrestype;
  codeLand: CodeLand;
  isCorrespondentie: boolean;
  beginDatum: moment.Moment;
  eindDatum: moment.Moment;
  attest: any;
}

@Component({
  selector: 'app-adres-form',
  templateUrl: './adres-form.component.html',
  styleUrls: ['./adres-form.component.scss']
})

export class AdresFormComponent implements OnInit {

  @ViewChild('f', { static: true }) FlowbackPersoneelslidAdresForm: EloketForm<FlowbackPersoneelslidAdresForm>;

  @Input() serverValidationError: ValidationBag;

  @Input() submitButtonText: string;

  @Input() set flowBackPersoneelslidAdres(value: FlowbackPersoneelslidAdres) {
    if (!value) {
      return;
    }

//only set form values after the data is loaded from the api because it was being accessed in select-component before it arrived
    this.dataLoaded.subscribe(loaded => {
      if(loaded){
          setFormValue(this.FlowbackPersoneelslidAdresForm, {
            straat: value.straat,
            straatLijn2: value.straatLijn2,
            huisNummer: value.huisNummer,
            busNummer: value.busNummer,
            codeAdresType: value.codeAdresType,
            codeGemeente: value.codeGemeente,
            codeLand: value.codeLand,
            beginDatum: moment(value.beginDatum),
            eindDatum: moment(value.eindDatum),
            isCorrespondentie: value.isCorrespondentie,
            attest: value.flowbackPersoneelslidAdresAttest
          });
          if (value.flowbackPersoneelslidAdresAttest) {
            this.attestAanwezig = true;
            this.attest = new FlowbackPersoneelslidAdresAttest(value.flowbackPersoneelslidAdresAttest);
          }
      }
    });

    }
      
  @Output() public flowbackPersoneelslidAdresChange = new EventEmitter<FlowbackPersoneelslidAdresForm>();

  minDateActiefVanaf: moment.Moment = moment(new Date());
  codeAdrestypeSelectConfig: ModelSelectConfig<CodeAdrestype>;
  codeAdrestypes: CodeAdrestype[];

  codeGemeenteSelectConfig: ModelSelectConfig<CodeGemeente>;
  codeGemeenten: CodeGemeente[];

  codeLandSelectConfig: ModelSelectConfig<CodeLand>;
  codeLanden: CodeLand[];

  fileToUpload: File = null;
  attestAanwezig: boolean = false;
  attest: FlowbackPersoneelslidAdresAttest;

  loaded: boolean = false;

  //added Subject<boolean>
  dataLoaded = new Subject<boolean>();

  constructor(private confirmationService: ConfirmationService, private codeTabelService: CodeTabelService) {

    //do these methods in order, make sure that loadCodeLanden is the last one, then set loaded boolean in loadCodeLanden
    this.loadCodeAdrestypes()
      .then(() => {
        return this.loadCodeGemeenten();
        })
        .then(() => {
          return this.loadCodeLanden();
          });

  }

  ngOnInit(): void {

  }

  public async handleFileInput(files: FileList) {
    this.fileToUpload = files.item(0);
  }

  savePersoneelslidAdres({ valid, value }: EloketForm<FlowbackPersoneelslidAdresForm>) {
    if (valid) {
      console.log("savePersoneelslidAdres", value);
      value.attest = this.fileToUpload;
      this.flowbackPersoneelslidAdresChange.emit(value);
    }
  }

  async HaalAttest(id: number) {
    //todo: implement
    let bewijs = null;
    let blob = convertByteArrayToBlob(bewijs.data.content, bewijs.data.contentType);
    FileSaver.saveAs(blob, bewijs.data.fileName.substr(9));

  }

  async DeleteAttest(id: number) {
    const confirmed = await this.confirmationService.promptConfirm('Personalia.Bank.VerwijderenAttestConfirm');
    if (confirmed) {
      //todo: implement
      var deleted = true;
      if (deleted) {
        this.attestAanwezig = false;
      }
    }
  }

  async loadCodeAdrestypes() {
    this.codeAdrestypes = [];
    const codeAdrestypeDto = await this.codeTabelService.GetCodeAdrestypes().toPromise();
    this.codeAdrestypes = codeAdrestypeDto.map(item => new CodeAdrestype(item))
                                          .sort((a, b) => (b.omschrijving < a.omschrijving ? 1 : -1));

    this.codeAdrestypeSelectConfig = new ModelSelectConfig(this.codeAdrestypes,
                                                          codeAdrestype => codeAdrestype.codeAdrestypeId.toString(), 
                                                          codeAdrestype => codeAdrestype.omschrijving);
  }

  async loadCodeGemeenten() {
    this.codeGemeenten = [];
    const codeGemeenteDto = await this.codeTabelService.GetCodeGemeentes().toPromise();
    this.codeGemeenten = codeGemeenteDto.map(item => new CodeGemeente(item))
                                        .sort((a, b) => (b.postNrGemeente < a.postNrGemeente ? 1 : -1));

    this.codeGemeenteSelectConfig = new ModelSelectConfig(this.codeGemeenten,
                                                          codeGemeente => codeGemeente.codeGemeenteId.toString(), 
                                                          codeGemeente => codeGemeente.postNrGemeente.toString() + ' ' + codeGemeente.gemeente);

  }

  async loadCodeLanden() {
    this.codeLanden = [];
    const codeLandDto = await this.codeTabelService.GetCodeLanden().toPromise();
    this.codeLanden = codeLandDto.map(item => new CodeLand(item))
                                          .sort((a, b) => (b.naam < a.naam ? 1 : -1));

    this.codeLandSelectConfig = new ModelSelectConfig(this.codeLanden,
                                                        codeLand => codeLand.codeLandId.toString(), 
                                                        codeLand => codeLand.naam);

    //set Subject<boolean> to true
    this.dataLoaded.next(true);

  }
}

相关问题