I'm trying to create a dynamic reactive form, but the value is not being displayed
<div *ngFor="let deliveryAcross of (deliveriesAcross | async)!; let i = index;">
<app-delivery-across
[index]="i"
[deliveryAcross]="deliveryAcross"
></app-delivery-across>
{{ deliveryAcross | json }}
</div>
deliveryacross.component.ts
@Input("deliveryAcross") deliveryAcross: IDeliverAcross;
minFormControl: FormControl;
errorStateMatcher: NextErrorStateMatcher;
constructor(private change: ChangeDetectorRef, private store: Store) {
this.deliveryAcross = {
iso: "",
min: 1,
max: 2,
shippingCents: 0,
shippingEuros: 0,
};
this.minFormControl = new FormControl("", [
Validators.required,
Validators.min(1),
]);
this.errorStateMatcher = new NextErrorStateMatcher();
}
I can't use ngModel
because it would cause readonly errors that's why I choose to use value instead, but my value is not being displayed rather the input refreshes back to empty
<mat-form-field
class="full-width"
[@transformRightLeftStateTrigger]="stateDown | async"
>
<input
matInput
[formControl]="minFormControl"
[errorStateMatcher]="errorStateMatcher"
placeholder="Minimaal"
appDeliveryAcross
[value]="deliveryAcross.min"
autocomplete="off"
[key]="'min'"
[component]="'delivery-across'"
type="number"
/>
</mat-form-field>
Why the value that comes from deliveryAcross.min
is not displayed in input?
That happens because you're using value
side by side with formControl
as a source of value for the input, so the initial value of formControl
overrides the value
one.
You can try to use one source such as formControl
, then use ngOnChanges
to get the changes of this.deliveryAcross
input, so you can write it again to the formControl
.
Try the following:
ngOnInit() {
// Move this part to the `ngOnInit` so you can read the value of `this.deliveryAcross` input,
// and set it as initial value of the form-control.
this.minFormControl = new FormControl(this.deliveryAcross?.min, [
Validators.required,
Validators.min(1)
]);
}
// implement `OnChanges` interface to get the input changes.
ngOnChanges(changes: SimpleChanges) {
if(changes.deliveryAcross) {
this.minFormControl.setValue(this.deliveryAcross?.min);
}
}
<mat-form-field
class="full-width"
[@transformRightLeftStateTrigger]="stateDown | async"
>
<input
matInput
[formControl]="minFormControl"
[errorStateMatcher]="errorStateMatcher"
placeholder="Minimaal"
appDeliveryAcross
autocomplete="off"
[key]="'min'"
[component]="'delivery-across'"
type="number"
/>
</mat-form-field>