1
votes

Originally created as a Angular 2 Template Form, in order to add auto save feature we are converting to a Reactive Form.

The page has a series of text inputs, persisted to the backend database via .NET Web API. Angular services call the web api.

I have created a FormGroup representing the page's data controls:

const cells = fb.group({
        id: [''],
        question: [''],
        actual: [''],
        budget: [''],
        average: [''],
        top20: ['']            
});
this.form = fb.group({
    reviewer: '',
    position: '',
    officeName: '',
    comments1: '',
    comments2: '',
    comments3: '',
    rows: fb.array([cells, cells])
});

The reviewer, position, officeName, and comments fields are working as expected, but I'm having trouble understanding how to represent a data set that is returned as a double array of rows and cells (a grid) within the FormGroup successfully.

In the Template Form version the grid data is received by an observable, like this:

    this.rows = summaryReportQuestion.map(summaryReportQuestionObj => {
        return {
            cells: [
                summaryReportQuestionObj.questionID,
                summaryReportQuestionObj.question,
                (summaryReportQuestionObj.columnSign == '$' ? (summaryReportQuestionObj.columnSign + ' ' + summaryReportQuestionObj.target) : summaryReportQuestionObj.target + ' ' + summaryReportQuestionObj.columnSign),
                (summaryReportQuestionObj.budget == null ? summaryReportQuestionObj.budget : (summaryReportQuestionObj.columnSign == '$' ? summaryReportQuestionObj.columnSign + ' ' + this.utilityService.formatNumberWithCommas(Math.floor(summaryReportQuestionObj.budget), false) : summaryReportQuestionObj.budget + ' ' + summaryReportQuestionObj.columnSign)),
                (summaryReportQuestionObj.average == null ? summaryReportQuestionObj.average : (summaryReportQuestionObj.columnSign == '$' ? summaryReportQuestionObj.columnSign + ' ' + this.utilityService.formatNumberWithCommas(Math.floor(summaryReportQuestionObj.average), false) : summaryReportQuestionObj.average + ' ' + summaryReportQuestionObj.columnSign)),
                (summaryReportQuestionObj.top20Percent == null ? summaryReportQuestionObj.top20Percent : (summaryReportQuestionObj.columnSign == '$' ? summaryReportQuestionObj.columnSign + ' ' + this.utilityService.formatNumberWithCommas(Math.floor(summaryReportQuestionObj.top20Percent), false) : summaryReportQuestionObj.top20Percent + ' ' + summaryReportQuestionObj.columnSign))
            ]
        };
    });

In the Reactive Form version I have just assigned the value of this.rows to my FormGroup item:

this.molForm.patchValue({rows: this.rows});

But it's not working as I expect.

What is the best way to use a double array with Form Groups?

1

1 Answers

1
votes

Since it is a lengthy list of controls, I will try to use a cell-size of 2 in each row, say for questionId and question. You can create one formGroup for the entire table of controls where each column/cell is denoted by a control which initialized as a FormArray, each of which consists of an array of FormControls (which when you visualize it, is the corresponding cell values going down each column/cell).

Suppose you had 2 rows, with values

(name of controls) -->      questionId              question          

  (row1 values)    -->         '1'               'First Question'

  (row2 values)    -->         '2'               'Second Question'

The FormGroup for this table can be initialized as,

this.tableControl = this.formbuilder.group({
 questionId: new FormArray([new FormControl('1'), new FormControl('2')]),
 question: new FormArray([new FormControl('First Question'), new FormControl('Second Question')])
});

You can further develop this for the remaining cells. You can also play with the FormArray control properties as given here for manipulating (inserting/removing etc) each of the controls present in this tableControl FormGroup. Hope it helps.