Search code examples
angulartypescriptangular-reactive-formsformarray

How to set different text in placeholder of my mat input in formArray?


I have a formArray in my mat-table where three rows are displayed. Now I want to have a different text for placeholder in each row in the column name, for example test1, test2, test3. What is the best way to implement this?

My Code:

<div formArrayName="rows" *ngIf="attributesWithFormControls.includes(column.attribute); else otherColumns">
                  <span id="edit-cell" [formGroupName]="i">
                      <mat-form-field id="edit-calc-input">
                        <label>
                          <input matInput type="text" [formControlName]="column.attribute">
                        </label>
                      </mat-form-field>
                  </span>
                </div>
  // To use input fields in template
  public attributesWithFormControls = [
    "productNumber",
    "name",
    "weight",
    "amount"
  ];
ngOnInit() {
    this.columns = this.displayedColumns.map(c => c.attribute);

    if (this.dataSource === null) {
      this.dataSource = new MatTableDataSource([]);
    }

    // myForm
    this.myForm = this.formBuilder.group({
      rows: this.formBuilder.array([this.initItemRows()])
    });
  }

// Convenience getter for easy access to form fields
  get f() {
    return this.myForm.controls;
  }

  get formArr() {
    return this.myForm.get("rows") as FormArray;
  }

  initItemRows() {
    return this.formBuilder.group({
      productNumber: [""],
      name: [""],
      weight: [""],
      amount: [""]
    });
  }

Here is my work in StackBlitz


Solution

  • REVISION USING FORM CONTROL

    If you wanted to do this from your formGroup, you could accomplish this with the following.

    Create a helper function to return the placeholder text base on index

    // return row placeholder
     getPlaceholder(i) {
       switch (i) {
         case 0:
           return "test";
           break;
         default:
           return "test" + i;
           break;
       }
     }
    

    In your addRow function get the placeholder text and set it to the property placeholder in your newItem.value object

     addRow() {
       for (let i = 0; i < 3; i++) {
         const newItem = this.initItemRows();
         newItem.value["placeholder"] = this.getPlaceholder(i);
         this.formArr.push(newItem);
         this.dataSource.data = this.dataSource.data.concat(newItem.value);
       }
     }
    

    In your HTML markup access that property value from the row

    <input
        matInput
        type="text"
        [placeholder]="row.placeholder"
        [formControlName]="column.attribute"
     />
    

    STACKBLITZ

    https://stackblitz.com/edit/angular-l9x7ac-oxq4qq?file=app/table-basic-example.html


    REVISION NON FORM CONTROL

    Create a helper function to return the placeholder text base on index

     // return row placeholder
      getPlaceholder(i) {
        switch (i) {
          case 0:
            return "test";
            break;
          default:
            return "test" + i;
            break;
        }
      }
    

    In HTML markup via the placeholder attribute call the helper function and pass i as the argument.

    <input
        matInput
        type="text"
        [placeholder]="getPlaceholder(i)"
        [formControlName]="column.attribute"
    />
    

    STACKBLITZ

    https://stackblitz.com/edit/angular-l9x7ac-6aq6u6?file=app%2Ftable-basic-example.html


    ORIGINAL ANSWER

    Modify your interface to include placeholder property.

    // Interface
    export interface MyInterface {
      attribute: string;
      name: string;
      placeholder: string;
    }
    

    Add property with placeholder value to your column attributes array.

    public displayedColumns: MyInterface[] = [
        { attribute: "productNumber", name: "ProductID", placeholder: "test1" },
        { attribute: "name", name: "Name", placeholder: "test2" },
        { attribute: "weight", name: "Weight", placeholder: "test3" },
        { attribute: "amount", name: "Price", placeholder: "test4" }
      ];
    

    In HTML markup, use the placeholder attribute on the matInput and pass in your value via [placeholder]="column.placeholder"

    <input
        matInput
        type="text"
        [placeholder]="column.placeholder"
        [formControlName]="column.attribute"
     />
    

    STACKBLITZ

    https://stackblitz.com/edit/angular-l9x7ac-psmqzu?file=app/table-basic-example.html