 
 
            The underlying data model / API is nearly the same - it's about where the data model is defined - either the view or the component class.
const contactForm = new FormGroup<ContactFormType>({
  name: new FormGroup<NameFormType>({
    first: new FormControl('Juana'),
    last: new FormControl('Garcia')
  }),
  email: new FormControl('')
});// types used above
interface ContactFormType {
  name: FormGroup<NameFormType>;
  email: FormControl<string | null>;
}
type NameFormType = {
  first: FormControl<string | null>;
  last: FormControl<string | null>;
};... and can be bound by
<form [formGroup]="contactForm" novalidate>
  <div formGroupName="name">
    <div>
      <label>First Name</label>
      <input type="text" formControlName="first">
    </div>
    <div>
      <label>Last Name</label>
      <input type="text" formControlName="last">
    </div>
  </div>
  <div>
    <label>E-Mail</label>
    <input type="email" formControlName="email">
  </div>
  <button type="submit">Submit</button>
</form>[formGroup]="contactForm" binds upper FormGroupformGroupName binds child FormGroupformControlName binds child FormControl... creates the same FormGroup-FormControl tree
interface ContactFormType {
  name: FormGroup<NameFormType>;
  email: FormControl<string | null>;
}
type NameFormType = {
  first: FormControl<string | null>;
  last: FormControl<string | null>;
};
@Component({ ... })
export class FormTestComponent implements OnInit {
  contactForm: FormGroup;
  constructor(private formBuilder: FormBuilder) { }
  ngOnInit(): void {
	  contactForm = this.formBuilder.group({
	    name: this.formBuilder.group({
	      first: "Juana",
	      last: "Garcia",
	    }),
	    email: "",
	  });
  }
} ... in Model Driven forms
  this.contactForm = this.formBuilder.group({
    name: this.formBuilder.group({
      first: "Juana",
      last: ["Garcia", Validators.required],
    }),
    email: ["", Validators.email],
  });FormControl and FormGroup both extend AbstractControlvalueChanges and statusChanges provide ObservablesFormControl has single controls statusFormGroup has aggregated status of child controlsinterface ValidatorFn {
    (c: AbstractControl): {
        [key: string]: any;
    } | null;
}ValidatorFn takes an AbstractControl to validate.
Returns null if valid.
Returns {[key: string]: any} as error definition.
Higher order function can return ValidatorFn
which returns { forbiddenName: name } as error.
function forbiddenName(forbiddenName: string): ValidatorFn {
  return (control: AbstractControl): ValidationErrors => {
    const name = control.value;
    const isForbidden = forbiddenName === name;
    return isForbidden ? { forbiddenName: name } : null;
  };
}behaves just like Angular Validators
FormControl.errors is extended by custom error key-value pairs from validation method.
<div 
  *ngIf="contactForm.controls.name.controls.first.getError('forbiddenName')">
  The name is not allowed.
</div>Live Code Examples & Backup slides below
Following slides are not subject of the lecture.
Ask trainers in case of questions.
<form #contactForm="ngForm" (ngSubmit)="submit(contactForm.value)">
	  <div ngModelGroup="name">
		<label for="first">First Name</label>
		<input type="text" name="first" ngModel>
		<label for="last">Last Name</label>
		<input type="text" name="last" ngModel>
	  </div>
	  <label for="email">E-Mail</label>
	  <input type="text" name="email" ngModel>
	  <button type="submit">Submit</button>
	</form>
	{ name: { first: string, last: string }, email:string }
			<input name=first ngModel>creates property inside forms data model with key 'first'
<input name=first [ngModel]="varName">creates one-way binding - binds a default value
	<input name=first [(ngModel)]="varName">
	<input name=first [ngModel]="varName" (ngModelChange)="varName=$event">creates two-way binding. Note: state at two places (component member and forms model)
<div ngModelGroup=group></div>creates nested object called group inside forms data model (form.value)
... in Template Driven forms
<input name=otto ngModel required minlength=4 maxlength=24><form #form=ngForm>
	  <input name=otto ngModel required>
	  <div *ngIf=form.controls.otto.errors>
		<div [hidden]="!form.controls.otto.errors.required">
			<span>Otto is really important!</span>
		</div>
		
	  </div>
	</form>form and ngModelGroup aggregate underlying controls (combined errors)
					Adding custom validators to Template Driven forms via Directives
<input type="text" name="first" ngModel noForbiddenName>NG_VALIDATORS dependency via providers property (directive meta data)validate() for directive and call validator - e.g. forbiddenNameValidator@Directive({
	  selector: '[noForbiddenName][ngModel],[noForbiddenName][formControl],[noForbiddenName][formControlName]',
	  providers: [{ 
			provide: NG_VALIDATORS, 
			useExisting: forwardRef(() => ForbiddenNameValidator), 
			multi: true 
	  }]
	})
	export class ForbiddenNameValidator implements Validator {
	  validator = forbiddenNameValidatorFn;
	  validate(c: FormControl) {
		return this.validator(c);
	  }
	}