5.Create AddAttendeeComponent

In this section we will make a presentational component to add attendees.

1. Create add AddAttendeeComponent

  • Add the component with the following command

ng g c event/components/add-attendee

2. Create a Attendee interface

It is encouraged to make many custom interfaces and discouraged to leave code un-typed. It is important to note these interfaces do not get added to the JavaScript bundled and sent to the browser, so adding them to a global folder like this is acceptable in this respect.

  • Create a models folder on the root of the app folder.

  • Add a Attendee interface file to the models folder with the below code.

src/app/models/attendee.ts
export interface Attendee {
    name: string;
    guests: number;
    attending: boolean;
}

In Angular and NgRx in particular it is very common to make an index.ts file which acts as a public API for a section of code like a models folder or a feature module. Everything that is meant to be shared from this section of code is described here, helping other developers know what by design is to be consumed from each section of an app.

  • Create an index.ts file to the models folder to re-export all the interfaces we make as we go, starting with our Attendee interface.

src/app/models/index.ts
export * from './attendee';

3. Add AddAttendeeComponent selector to event container

  • Add the AddAttendeeComponent to the EventComponent.

src/app/event/containers/event/event.component.html
<app-add-attendee></app-add-attendee>

4. Add ReactiveFormsModule to EventModule

In Angular you have "Template Driven" and "Reactive Forms". Reactive forms are the newer of the two and the recommended approach from the Angular team. Reactive forms are powerful and flexible with the ability to configure in code making it easy to change forms dynamically, listening to field changes as observables and make custom asynchronous validation simple.

  • Import the ReactiveFormsModule into EventModule and register it in the imports array of the @NgModule decorator.

src/app/event/event.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { ReactiveFormsModule } from '@angular/forms';

import { EventComponent } from './containers/event/event.component';
import { AddAttendeeComponent } from './components/add-attendee/add-attendee.component';

@NgModule({
  imports: [
    CommonModule,
    RouterModule.forChild([{ path: '', component: EventComponent }]),
    ReactiveFormsModule
  ],
  declarations: [EventComponent, AddAttendeeComponent]
})
export class EventModule {}

5. Add input and reactive form to AddAttendeeComponent

To keep this presentational component simple and avoid injecting in dependencies making it harder to mock we will not use the popular FormBuilder from Angular. We only have a single field orFormControl in our FormGroup but it is easy to imagine how we could add more to this addAttendeeForm.

  • Remove the constructor and ngOnInit lifecycle hook from the component, further helping other developers know this is a presentational component and should not need a constructor.

  • Add addAttendeeForm reactive form, FormGroup and FormControl.

src\app\event\components\add-attendee\add-attendee.component.ts
import { Component } from '@angular/core';
import { Attendee } from '../../../models';
import { FormGroup } from '@angular/forms';
import { FormControl } from '@angular/forms';
import { Validators } from '@angular/forms';

@Component({
  selector: 'app-add-attendee',
  templateUrl: './add-attendee.component.html',
  styleUrls: ['./add-attendee.component.scss']
})
export class AddAttendeeComponent {
  addAttendeeForm = new FormGroup({
    name: new FormControl('', [Validators.required])
  });
}
  • Add submit method to be executed when someone hits the add button in the HTML template.

  • In the submit method build up a new attendee constant which we can add on the attending and guests fields we have not yet implemented in our form.

  • Console log the submitted value until the next section when we emit the submitted form out of this presentational component to be listened to by the parent container component.

I am using the Turbo Console Visual Studio Extension to make more readable log messages.

src\app\event\components\add-attendee\add-attendee.component.ts
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';

import { Attendee } from '../../../models';

@Component({
  selector: 'app-add-attendee',
  templateUrl: './add-attendee.component.html',
  styleUrls: ['./add-attendee.component.scss']
})
export class AddAttendeeComponent {
  addAttendeeForm = new FormGroup({
    name: new FormControl('', [Validators.required])
  });

  submit() {
    const attendee = {
      name: this.addAttendeeForm.value.name,
      attending: true,
      guests: 0
    };
    console.log('TCL: AddAttendeeComponent -> submit -> attendee', attendee);
  }
}

6. Add form to component HTML

  • Create a HTML form element and add an angular [formGroup] binding to angularize the form.

  • and (ngSubmit) event handler to call our submit method when the form is submitted. We do not need to pass the form value over we can grab in in the template from the addAttendeeForm.

  • Bind the name field of our FormControl to the input element with angular's formControlName attribute.

src/app/event/components/add-attendee/add-attendee.component.html
<form [formGroup]="addAttendeeForm" (ngSubmit)="submit()">
    <input type="text" formControlName="name">
    <button type="submit" >submit</button>
</form>

7. Add CSS styles to component SCSS file

  • Add styles to make the button and input element inline next to each other.

src/app/event/components/add-attendee/add-attendee.component.scss
form {
  display: flex;
}

8. Submit form and check it's value

  • Start the app and check the correct value is logged to the console when you submit a name.

Last updated