2

In my Angular project, I have a Product component, which contain a Reactive Form:

this.productForm = this.formBuilder.group({
       prodid: ['', [Validators.required]],
       prodname: ['', [Validators.required]],
       prodprice: ['', [Validators.required, Validators.pattern(/^[.\d]+$/)]],
       picture: ['', [Validators.required]],
       category: ['', [Validators.required]]
   });

In the HTML page i'm setting the value of the fields, using [value], as follows:

<form [formGroup]="productForm" (ngSubmit)="onSubmit()">
        <div class="form-group">
            <label>Id</label>
            <input type="text" formControlName="prodid" class="form-control" readonly [value]="currentProduct!=null?currentProduct.product_id:null" />
        </div>
        <div class="form-group">
            <label>Name</label>
            <input type="text" formControlName="prodname" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.prodname.errors }"
             [value]="currentProduct!=null?currentProduct.product_name:null" />
            <div *ngIf="submitted && f.prodname.errors" class="invalid-feedback">
                <div *ngIf="f.prodname.errors.required">Name is required</div>
            </div>
        </div>

        <div class="form-group">
            <label>Price</label>
            <input type="number" formControlName="prodprice" class="form-control" 
             [ngClass]="{ 'is-invalid': submitted && f.prodprice.errors }" step="0.01" 
             [value]="currentProduct!=null?currentProduct.price:null" />
            <div *ngIf="submitted && f.prodprice.errors" class="invalid-feedback">
                <div *ngIf="f.prodprice.errors.required">Price is required</div>
                <div *ngIf="f.prodprice.errors.pattern">Price is invalid</div>
            </div>
        </div>
        <div class="form-group">
            <label>Picture Path</label>
            <input type="text" formControlName="picture" class="form-control" 
             [ngClass]="{ 'is-invalid': submitted && f.picture.errors }" 
             [value]="currentProduct!=null?currentProduct.img_path:null" />
            <div *ngIf="submitted && f.picture.errors" class="invalid-feedback">
                <div *ngIf="f.picture.errors.required">Picture Path is required</div>
            </div>
        </div>
        <div class="form-group">
            <label>Category</label>
            <select formControlName="category" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.category.errors }" 
             [value]="currentProduct!=null?currentProduct.category_id:null">
                <option  *ngFor="let cat of arrCategories" value="{{cat.id}}" >{{cat.name}}</option>
            </select>
            <div *ngIf="submitted && f.category.errors" class="invalid-feedback">
                <div *ngIf="f.category.errors.required">Category is required</div>
            </div>
        </div>
        {{productForm.value | json }}

The fields value are displayed correctly, with the correct value, but the {{productForm.value}} is empty, and when pressing Submit, the required error is being raised.

Please note, if I manually enter a value into the fields, it's ok. it's empty only if the value is being set by [value] in the html code, and does not being changed manually.

Any idea?

6
  • 1
    Working fine here:stackblitz.com/edit/pmp-dynamic-formcontrol-wbzt1r Commented Nov 4, 2019 at 13:37
  • please see my comment in the post. Commented Nov 4, 2019 at 13:43
  • Unable to understand! Can you please explain? Commented Nov 4, 2019 at 13:45
  • I'm first set the value of the fields in the html using [value]="currentProduct!=null?currentProduct.img_path:null". currentProduct is an object with data of some product. the data is being displayed correctly in the fields. but the value is not really set the form value. it is only being displayed. Commented Nov 4, 2019 at 13:48
  • Have you got an answer? Commented Nov 5, 2019 at 7:47

1 Answer 1

2

You can provide an initial value to your reactive form. You can check this example on Stackblitz

Also, you need to provide a value with ngValue to the option.

this.productForm = this.formBuilder.group({
       prodid: [currentProduct? currentProduct.product_id:null, [Validators.required]],
       prodname: [currentProduct? currentProduct.product_name:null, [Validators.required]],
       prodprice: [currentProduct? currentProduct.price:null, [Validators.required, Validators.pattern(/^[.\d]+$/)]],
       picture: [currentProduct? currentProduct.img_path:null, [Validators.required]],
       category: [currentProduct? currentProduct.category_id:null, [Validators.required]]
   });

To change form value dynamically you can use pathValue like the following;

  setFormData(){
    const newValue = {
    prodid: "newId",
    prodname: "newName",
    prodprice: "12346567",
    picture: "newPicture",
    category: "2"
    };
    this.productForm.patchValue(newValue);
  }

an on your template you don't need to use value anymore.

<form [formGroup]="productForm" (ngSubmit)="onSubmit()">
        <div class="form-group">
            <label>Id</label>
            <input type="text" formControlName="prodid" class="form-control" readonly />
        </div>
        <div class="form-group">
            <label>Name</label>
            <input type="text" formControlName="prodname" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.prodname.errors }" />
            <div *ngIf="submitted && f.prodname.errors" class="invalid-feedback">
                <div *ngIf="f.prodname.errors.required">Name is required</div>
            </div>
        </div>

        <div class="form-group">
            <label>Price</label>
            <input type="number" formControlName="prodprice" class="form-control" 
             [ngClass]="{ 'is-invalid': submitted && f.prodprice.errors }" step="0.01" />
            <div *ngIf="submitted && f.prodprice.errors" class="invalid-feedback">
                <div *ngIf="f.prodprice.errors.required">Price is required</div>
                <div *ngIf="f.prodprice.errors.pattern">Price is invalid</div>
            </div>
        </div>
        <div class="form-group">
            <label>Picture Path</label>
            <input type="text" formControlName="picture" class="form-control" 
             [ngClass]="{ 'is-invalid': submitted && f.picture.errors }" />
            <div *ngIf="submitted && f.picture.errors" class="invalid-feedback">
                <div *ngIf="f.picture.errors.required">Picture Path is required</div>
            </div>
        </div>
        <div class="form-group">
            <label>Category</label>
            <select formControlName="category" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.category.errors }" >
                <option  *ngFor="let cat of arrCategories" [ngValue]="cat.value" >{{cat.name}}</option>
            </select>
            <div *ngIf="submitted && f.category.errors" class="invalid-feedback">
                <div *ngIf="f.category.errors.required">Category is required</div>
            </div>
        </div>
        {{productForm.value | json }}
    <button type="button" (click) ="setFormData()">Change Form Data</button> <!-- this button for change form data dynamically -->
Sign up to request clarification or add additional context in comments.

8 Comments

i'm not sure if this will be good for me. I have two sibling components. one with products list and one with product details. when clicking on a product I'm updating the currentProduct object and the form fields should be updated. this way, will it be initialized only once or whenever there is a change in currentProduct it will be reflected in the form?
You can use patchValue to do it. I will edit my answer.
I edited my answer. I hope it will be helpful for you. @devora
Don't forget to check it as an valid answer if it is, Thanks.
it might work, I just wonder how to implement it in my situation: I have 2 components: component A which contain list of products. component B which contain the productForm. when clicking on a product in component A, the patchValue in component B should be executed to update the productForm fields with the data of the selected product. @nevzatopcu
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.