0

I've been working with Angular for a bit and I know my way decently around Reactive forms and template-driven forms but I am having trouble with this problem, especially Angular's Reactive Form Array.

API response that I wish to POST/PUT to is formed like this, where the user is able to add a row and a dropdown will let them select the property, in this case, it's "p", "h1", "h2" and so on and the value they wished to have typed

  "description": {
"body": [
  {
    "p": "test paragraph"
  },
  {
    "h1": "test header"
  }
],

I am in the process of converting our old JQuery and js nonsense to a Framework and it has been hard for me to wrap my mind on how to convert this process.

The user will click on Add item:
enter image description here

Then a row will be created via formArray I am assuming since I have tried this beforehand and it has worked but the dropdown to edit the property is giving me an issue.

enter image description here

And this is how it would look like when a few additional rows are created enter image description here

I understand how formArrays work via this example:
Dynamically Add Rows Based on Condition Using Reactive Forms in Angular

so I will need a getter, as well as the function that creates the dynamic form and HTML but I am currently stuck at the moment.

1
  • Also please note that I am doing this in angular 8, with material design and bootstrap 4. The project is using only reactive forms at the moment for all form submissions Commented Aug 29, 2020 at 17:08

1 Answer 1

0

I have eventually figured out most of the problem, we will be using Angular's FormBuilder, FormArrays, and template interpolation.

Start by defining the form with form builder:

text-form.ts

  this.textForm = this.fb.group({
  lang: null,
  description: this.fb.array([]),
});

You will be using Angular's getter in this case you want to grab description from the defined above form builder

  get descriptionItems() {
    return this.artifactTextForm.get('description') as FormArray;
  }

Then you will create two functions one is used in a button to add rows and the other to delete the current row at the index in the Array

This will be a bit different from other examples as we will be using some ES6 tricks

  addDescriptionItem() {
this.descriptionItems.push(this.fb.group({[this.selectedHeading]: ''}));
}

I defined this.selectedHeading as: at the top of my component class

  selectedHeading = 'h1';

Now create the button that will be created in the forloop on the template for each row

      // deleteDescriptionItem removes the item at the index given in the formArray
  deleteDescriptionItem(index: number) {
    this.descriptionItems.removeAt(index);
  }

Now comes one of the most important parts in the template to make sure everything looks nice. I am using Angular Material Design but it should work and perform the same natively.

    <form [formGroup]="artifactTextForm">

  <mat-dialog-content>

    <mat-form-field appearance="fill">
      <mat-label>Select Header Type</mat-label>
      <mat-select [(value)]="selectedHeading">
        <mat-option value="h1">Header 1</mat-option>
        <mat-option value="h2">Header 2</mat-option>
        <mat-option value="h3">Header 3</mat-option>
        <mat-option value="h4">Header 4</mat-option>
        <mat-option value="p">Paragraph</mat-option>
      </mat-select>
    </mat-form-field>

    <!-- Description form array -->
    <div formArrayName="description">
      <div *ngFor="let item of descriptionItems.controls; let i = index" [formGroupName]="i">
        <input
          [formControlName]="this.selectedHeading"
          placeholder="Enter Description Data"
          [maxLength]="formMaxLength">
        <button
          mat-raised-button
          color="primary"
          type="button"
          (click)="deleteDescriptionItem(i)">Delete Item</button>
      </div>
      <button mat-raised-button color="primary" type="button" (click)="addDescriptionItem()">Add Description</button>
    </div>
  </mat-dialog-content>

  <mat-dialog-actions>
    <button mat-raised-button type="submit" (click)="onSubmit()">Save</button>
    <button mat-raised-button type="reset" (click)="dialogRef.close()">Cancel</button>
  </mat-dialog-actions>
</form>

Make sure the add button is outside of the div with the forloop and it should something like so.

enter image description here

side note: Flame shot on ubuntu is amazing.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.