Search code examples
angularangular-forms

Error when I tried to create a template driven form


I want to create a temple driven form, and I want to access the values from the form, but I received this error :

CreateNewTaskComponent.html:8 ERROR TypeError: Cannot read property 'id' of undefined

This is my form:

<form #taskForm="ngForm" (ngSubmit)="addANewTask(taskForm.value)">
        <div class="form-group">
          <label for="id">Task Id:</label>
          <input [(ngModel)]="task.id"  type="text" class="form-control" name="id" id="id" placeholder="">
        </div>
        <div class="form-group">
          <label for="description">Description</label>
          <input [(ngModel)]="task.description"  type="text" class="form-control" name="description" id="description" placeholder="">
        </div>
        <div class="form-group">
          <label for="date">Date</label>
          <input [(ngModel)]="task.date"  type="text" class="form-control" name="date" id="date" placeholder="">
        </div>
        <button type="submit" class="btn btn-success">Submit</button>
        <button (click)="cancel()" type="cancel" class="btn btn-primary">Cancel</button>
      </form>

And this is my component:

  @Component({
  selector: 'app-create-new-task',
  templateUrl: './create-new-task.component.html',
  styleUrls: ['./create-new-task.component.css']
})
export class CreateNewTaskComponent implements OnInit {

  task: Task;

  constructor(
    private taskService: TaskService,
    private router: Router) {
  }

  addANewTask(form) {
    console.log(form);
  }

  cancel() {
    this.router.navigate(['/tasks']);
  }

  ngOnInit() {
     this.task = new Task(); //This line solved the issue
  }

}

I want to access values from the form... Could you please, tell me want I'm doing wrong?


Solution

  • Basically you have a component class, which implements OnInit. In most object-oriented environments one does the actual initialization inside the constructor, but not in Angular. In Angular, the constructor is initializing the class and not the component. Read more.

    So, basically you have an event hook, which is ngOnInit, which runs shortly after the constructor and ngOnInit will actually initialize the component. Your template will try to use task, assuming it's a property of the component, but will only be able to do so if it's initialized for the component.

    More about lifecycle hooks: https://angular.io/guide/lifecycle-hooks