2

I am trying to develop a reactive form quite similar to the angular2 tutorial. It works fine, however when I want to add new Question, I get the following error:

EXCEPTION: Error in ./RecommendationDetailsComponent class RecommendationDetailsComponent - inline template:45:40 caused by: Cannot find control with path: 'questions -> 1 -> id'

Removing a question works fine. Does anybody have an idea where I might find a solution. It is not clear to me what is exactly the problem right here.

The model :

export class Recommendation {
  _id?: string;
  recommendation: string;
  questions: Question[];
  }
}

export class Question {
  id: '';
  question: '';
  date: '';
}

the recommendation-details.component.ts

import { Component, Input, OnChanges } from '@angular/core';
import { FormArray, FormBuilder, FormGroup } from '@angular/forms';

import { Recommendation, Question } from '../recommendation';
import { RecommendationService } from '../recommendation.service';

@Component({
  selector: 'recommendation-details',
  templateUrl: './recommendation-details.component.html',
  styleUrls: ['./recommendation-details.component.css'],
  providers: [RecommendationService]
})

export class RecommendationDetailsComponent implements OnChanges {
  @Input()
  Recommendation: Recommendation;

  @Input()
  createHandler: Function;
  @Input()
  updateHandler: Function;
  @Input()
  deleteHandler: Function;

  recommendationForm: FormGroup;

  constructor (private fb: FormBuilder, private recommendationService: RecommendationService) {this.createForm()}

  // creatForm Creert een basisformulier om gegevens te wijzigen
  createForm() {
    this.recommendationForm = this.fb.group({
      recommendation: '',
      topic: '',
      secTopic: '',
      questions: this.fb.array([]),
    })
    console.log('Form created')
  }

  // Elke keer dat een andere Recommendation wordt gekozen, verander dan de waarden van het formulier
  ngOnChanges() {
    if (this.Recommendation == null) {
      console.log('waiting...');
    } else {
      this.recommendationForm.reset ({
        recommendation: this.Recommendation.recommendation
      })
      this.setQuestions(this.Recommendation.questions);
    }
  };

  get questions(): FormArray {
    return this.recommendationForm.get('questions') as FormArray;
      console.log(this.questions);
  }

  setQuestions(questions: Question[]) {
    console.log ('Hallo ' + questions[0].question);
    const questionFGs = questions.map(question => this.fb.group(question));
    const questionFormArray = this.fb.array(questionFGs);
    this.recommendationForm.setControl('questions', questionFormArray);
  }

  addQuestion () {
    console.log(this.questions);
    this.questions.push(this.fb.group(new Question()));
  }

  }
}

HTML

<form [formGroup]="recommendationForm" novalidate>
  <div class="form-group">
    <label class="center-block">Recommendation:
      <input class="form-control" formControlName="recommendation">
    </label>
  </div>

<div formArrayName="questions" class="well well-lg">
    <div *ngFor="let question of questions.controls; let i=index" [formGroupName]="i" >
      <!-- The repeated address template -->
      <h4>Question{{i + 1}}</h4>
      <div style="margin-left: 1em;">
        <div class="form-group">
          <label class="center-block">ID:
            <input class="form-control" formControlName="id">
          </label>
        </div>
        <div class="form-group">
          <label class="center-block">Question:
            <input class="form-control" formControlName="question">
          </label>
        </div>
        <div class="form-group">
          <label class="center-block">Date:
            <input class="form-control" formControlName="date">
          </label>
        </div>      
      </div>
    <button (click)="removeQuestion(i)" type="button">Remove</button>
    </div>
  <button (click)="addQuestion()" type="button">Add</button>
</div>
</form>
<p>recommendationForm value: {{ recommendationForm.value | json}}</p>
2
  • What is a template code? Commented Mar 17, 2017 at 13:20
  • @Roman C What do you mean by that? Commented Mar 17, 2017 at 13:35

1 Answer 1

2

Look carefully at the code:

export class Question {
  id: '';
  question: '';
  date: '';
}

Test

There are no properties on this class if you call new Question(). Angular executes Object.keys on value that you passed to fb.group method

_reduceControls(controlsConfig: {[k: string]: any}): {[key: string]: AbstractControl} {
  const controls: {[key: string]: AbstractControl} = {};
  Object.keys(controlsConfig).forEach(controlName => {
    controls[controlName] = this._createControl(controlsConfig[controlName]);
  });
  return controls;
}

In your case Object.keys(new Question()) will be []

So replace it with:

export class Question {
  id = '';
  question = '';
  date = '';
}

Plunker Example

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.