1

I have table with many rows that's generated with a ngFor loop. When the user clicks on a row or group of rows, those rows are pushed into a new array and can be edited one at a time. I want to add reset functionality that allows the user to reset the row back to it's default settings. The problem I'm having is the reset function is resetting the entire table. How can I pass the specific row to the reset method to ONLY reset that specific row?

Below is the relevant code. // HTML

<div
*ngIf="!!modal"
class="modal__mask">
<section
    *ngIf="!!modal"
    class="modal modal__large"
    [formGroup]="tableForm">
    <div class="modal__header modal__header--large">
        <h6>Edit Employee Details</h6>
        <div class='u-flex u-alignCenter'>
            <i
                class="icon icon--medium icon--pointer"
                (click)="previousSelectedRow()">
                arrow_left
            </i>
            <p *ngIf="selectedRows.length > 0">{{modalPage + 1}} of {{selectedRows.length}} employees</p>
            <i
                class="icon icon--medium icon--pointer"
                (click)="nextSelectedRow()">
                arrow_right
            </i>
        </div>
    </div>
    <section>
        <div
            class="u-flex u-wrap"
            *ngFor='let row of selectedRows; let i = index'>
            <div
                class="u-flex modal__body"
                style="width: 50%"
                *ngFor="let column of columns">
                <div
                    *ngIf="column.label"
                    class="input__wrapper"
                    [ngClass]="{'input__wrapper--inline': layout === 'horizontal'}">
                    <div>
                        <label
                            class="input__label">
                            <p class="t-bold t-data">{{column.label}}</p>
                        </label>
                        <div class="z-input__default">
                            <input
                                class="input u-maxX"
                                [attr.type]=""
                                [attr.placeholder]=""
                                [formControlName]="column.key"
                                [value]="row[column.key]">
                        </div>
                    </div>
                </div>
            </div>
           <section class="modal__footer u-fillRemaining">
                <div class="u-flex">
                    <button
                        class="button button--medium"
                        (click)="nextSelectedRow()">
                        <div class="button__content">
                            <i
                                class="icon icon--medium"
                                *ngIf="!!icon">
                                {{icon}}
                            </i>
                            <span>Skip</span>
                        </div>
                    </button>
                </div>
                <div class="u-flex">
                    <button
                        class="button button--low"
                        (click)="reset(row)">
                        <div class="button__content">
                            <i
                                class="icon icon--medium"
                                *ngIf="!!icon">
                                {{icon}}
                            </i>
                            <span>Reset</span>
                        </div>
                    </button>
                    <button class="button button--low">
                        <div class="button__content">
                            <i
                                class="icon icon--medium"
                                *ngIf="!!icon">
                                {{icon}}
                            </i>
                            <span>Save Changes</span>
                        </div>
                    </button>
                </div>
            </section>
        </div>
    </section>

</section>

// TS

ngOnInit() {
    if (!!this.rows) {
        this.tableForm = new FormGroup({});

        this.rows.forEach(row => {
            this.columns.forEach(column => {
                this.tableForm.addControl(column.key, new FormControl(row[column.key]));
            });
        })
    }
}

reset(row) {
    let resetRow = row;
    this.tableForm.reset(resetRow) // this resets the entire table

}
London804
  • 1,072
  • 1
  • 22
  • 47

1 Answers1

3

Basically now you have your controls going just one after another, so you cannot just distinguish which are related to the particular row, what you can do is to wrap controls of each row into the FormGroup and add this FormGroup into the parent FormArray so index of the row would be its key. Then you can use that index to find FormGroup of needed row to reset it.

In ngOnInit method

this.tableForm = new FormArray([]);

this.rows.forEach((row, i) => {
    const rowGroup = new FormGroup({});

    this.columns.forEach(column => {
        this.rowGroup.addControl(column.key, new FormControl(row[column.key]));
    });
    this.tableForm.push(rowGroup);
})

In html template

...
<section
   *ngIf="!!modal"
   class="modal modal__large"
   [formArray]="tableForm">
...
<div
  class="u-flex u-wrap"
  *ngFor='let row of selectedRows; let i = index'
   [formGroupName]="i">
...
<button
    class="button button--low"
    (click)="reset(i)">
....

reset method

reset(i) {
    this.tableForm.at(i).reset();
}

Hope that helps.

Amir Arbabian
  • 3,419
  • 1
  • 6
  • 12
  • 1
    this is more or less correct but the HTML template bindings need to be rewritten for this to work. The better option here would to be use a form array instead of an index keyed form group. – bryan60 Jan 28 '19 at 17:37
  • @bryan60 Yeah you are right, one second i will update answer – Amir Arbabian Jan 28 '19 at 17:39
  • @AmirArbabian excellent answer thank you very much! I knew the problem had to do with not having nested FormGroups I just wasn't able to figure out how to use formArray to solve the problem. – London804 Jan 28 '19 at 17:56
  • @London804 I'm glad that it helped you! – Amir Arbabian Jan 28 '19 at 19:07
  • @AmirArbabian I have a question related to this that I'm wondering if you could answer? When I make this.tableForm = new FormArray([]); I can't pass it to children components. Please see my question. https://stackoverflow.com/questions/54560559/error-error-cannot-find-control-with-name-object-object?noredirect=1#comment95920652_54560559 – London804 Feb 06 '19 at 19:13