javascript - Rätt sätt att sprida beräknat värde i Angular2


Jag vill använda beräknat värde via @Input-egenskaper

Men att sprida initialt värde fungerar inte bra.

https://plnkr.co/edit/1MMpOYOKIouwnNc3uIuy

Jag skapar App (rotkomponent med formulär styrt av mall) och NumComponent (barnkomponent som bara sparar inmatat värde) komponent.

När jag skickar en attribut till NumComponent som [useThree]="true" vill jag sedan sätta standardvärdet '3' till NumComponent

Men jag kan inte hitta ett sätt utan att använda setTimeout

Finns det ett sätt att sprida initialvärdet utan setTimeout?

Redigerad den 5/5

App-komponent

@Component({
  selector: 'my-app',
  template: `
    <div>
      <form novalidate #form="ngForm">
        <app-num name="num" ngModel [useThree]="true"></app-num>
      </form>
      <pre>{{form.value | json}}</pre>
    </div>
  `
})
export class App {}

NumComponent

export const NumValueAccessor = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => NumComponent),
  multi: true
};

@Component({
  selector: 'app-num',
  template: `<input [(ngModel)]="num" type="text" (ngModelChange)="updateValue()" />`,
  providers: [NumValueAccessor]
})
export class NumComponent implements ControlValueAccessor {
  num = 0;

  // I want set literal number 3 to `num` property
  // when `useThree` is true.
  @Input() useThree = false;

  onChange = (_: any) => {};

  updateValue(num = this.num) {
    this.onChange(String(num));
  }

  writeValue(value: string): void {
    if (this.useThree) {
      /**********
       * ISSUE
       **********/
      // this code is not work. after code ran, `NumComponent` has
      // value 3 but AppComponent's internal FormComponent value
      // is '' (empty string)
      // this.num = 3;
      // this.updateValue(3);

      // ran code with `setTimeout` solve this problem. but
      // I don't want using setTimeout for this feature.
      // setTimeout(() => {
      //   this.num = 3;
      //   this.updateValue(3);
      // }, 0);

      // Is there any way to propagate computed initial value?
      this.num = 3;
      this.updateValue(3);

      /**********
       * ISSUE
       **********/

      this.useThree = false;
      return;
    }
    this.num = Number(value);
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {}

  setDisabledState(isDisabled: boolean): void {}
}

Det verkar som att föräldrakomponenten inte inser det propagade värdet vid initialiseringslivscykeltiden.

Svar #1

Jag är inte säker på att jag har förstått problemet fullt ut, men en möjlig lösning på det du letar efter skulle kunna vara

private _useThree = false;
@Input() set useThree(value: boolean) {
     this._useThree = value;
     if (this._useThree) {
         this.num = 3;
     }
}

På så sätt, när du vill sätta värdet på input-egenskapen useThree från föräldrakomponenten, kör du faktiskt koden i setter-metoden som definierats ovan.