Can't acces FormControl instance directly. Cannot read property 'invalid' of undefined

It throws error because you don't have a variable called username or password.

In order to solve this, you can do the following:

export class SignUpComponent implements OnInit {

  myForm: FormGroup;
  usernameCtrl: FormControl;
  passwordCtrl: FormControl;

  ngOnInit() {
    this.usernameCtrl = new FormControl('username', Validators.required);
    this.passwordCtrl = new FormControl('', Validators.required);

    this.myForm = new FormGroup({
      username: this.usernameCtrl,
      password: this.passwordCtrl
    });
  }
}

... or using FormBuilder:

export class SignUpComponent implements OnInit {

  myForm: FormGroup;
  usernameCtrl: FormControl;
  passwordCtrl: FormControl;

  constructor(private formBuilder: FormBuilder) { }

  ngOnInit() {
    this.usernameCtrl = this.formBuilder.control('username', Validators.required);
    this.passwordCtrl = this.formBuilder.control('', Validators.required);

    this.myForm = this.formBuilder.group({
      username: this.usernameCtrl,
      password: this.passwordCtrl
    });
  }
}

Now you can use it directly in template, like this:

<div class="alert alert-danger" *ngIf="usernameCtrl.invalid">
  username is required
</div>

Also, if you prefer you can use [formControl] instead of formControlName:

<input 
  type="text"
  name="username"
  class="form-control"
  [formControl]="usernameCtrl">

PLUNKER


You can solve this issue using a Form Group and defining the corresponding getters in your controller. In order to achieve this goal:

In the controller:

1) Remove the form control variables definition and initialization

usernameCtrl: FormControl;
passwordCtrl: FormControl;
...
this.usernameCtrl = this.formBuilder.control('username',Validators.required);
this.passwordCtrl = this.formBuilder.control('', Validators.required);

2)Change the form group initialization to this

ngOnInit() {
this.myForm = this.formBuilder.group({
  username: ['usename', Validators.required]
  password: ['', Validators.required]
});

}

3) Add the getters

get username() { return this.myForm.get('username'); }
get password() { return this.myForm.get('password'); }

In the template:

1) add a parent div with [formGroup]="MyForm"

<div [formGroup]="myForm">
...
</div>

2) change [formControl]="usernameCtrl" for forcontrolName=username and *ngIf="usernameCtrl.invalid" for *ngIf="username.invalid"

<input type="text"
       name="username"
       class="form-control"
       formControlName="username">
  <div *ngIf="username.invalid" class="alert alert-danger"> 
    username is required
  </div>

3) change [formControl]="passwordCtrl" for forcontrolName=password and *ngIf="passwordCtrl.invalid" for *ngIf="password.invalid" te.

<input type="text"
       name="password"
       class="form-control"
       formControlName="password">
  <div *ngIf="password.invalid" class="alert alert-danger">
    password is required
  </div>

Plunker


For me works:

form.component:

getFormControl(name) {
    return this.Form.get(name);
}

template:

<input 
  type="text"
  name="username"
  class="form-control"
  formControlName="username"
>
<div *ngIf="getFormControl('username').invalid" class="alert alert-danger">
  username is required
</div>