For working session while interviewing candidates. This focuses on lazy loading and creating a Reactive Form.
https://github.com/angular/angular-cli/wiki/stories-include-bootstrap
- Run
npm install bootstrap@next --save
. - Add
"../node_modules/bootstrap/dist/css/bootstrap.min.css"
toapp[0].styles
property of file.angular-cli.json
.
In app.component.html
:
- Remove default code.
- Add Bootstrap grid container.
- Optional Add a Bootstrap navbar element.
- Run angular-cli command
ng g m form --routing
to generateFormModule
andFormRoutingModule
.- Note: Can also generate
FormRoutingModule
separately if--routing
flag not used.
- Note: Can also generate
- Run angular-cli command
ng g c form/form
to generateFormComponent
. - Add new route definition in
form-routing.module.ts
:{ path: '', component: FormComponent }
- Add new route definition in
app-routing.module.ts
:
{ path: 'form', loadChildren: './form/form.module#FormModule' },
{ path: '**', redirectTo: 'form' }
- Verify it works by going to any path and seeing that it redirects to '/form' and Network debugging tool shows a
___.chunk.js
.
-
Import
ReactiveFormsModule
toFormModule
. -
In
FormComponent
, create the FormGroup for form (eg login form with username and password):- Method 1: Use FormBuilder to build out FormGroup
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; ... public loginForm: FormGroup; constructor(private formBuilder: FormBuilder) {} ngOnInit() { this.loginForm = this.formBuilder.group({ username: ['', Validators.required, Validators.minLength(4)], password: ['', Validators.required, Validators.minLength(8)] }); }
- Method 2: Define FormGroup object and explicitly declare each prop as a FormControl.
import { FormControl, FormGroup, Validators } from '@angular/forms'; ... public loginForm: FormGroup; constructor(private formBuilder: FormBuilder) {} ngOnInit() { this.loginForm = new FormGroup({ username: new FormControl('', [Validators.required, Validators.minLength(4)]), password: new FormControl('', [Validators.required, Validators.minLength(8)]) }); }
- Create form template and bind the FormGroup to template of
FormComponent
. Adhere to the following requirements:- Submit button should be disabled if the FormGroup is invalid.
- Add basic validation error msg per input that shows if FormControl has been touched and it is invalid.
- Don't bind submit event for now.
<form [formGroup]="loginForm"> <div> <label for="username">Username</label> <input type="text" id="username" formControlName="username" /> <div [hidden]="loginForm.get('username').valid || loginForm.get('username').untouched">Username is required</div> </div> <div> <label for="password">Password</label> <input type="password" id="password" formControlName="password" /> <div [hidden]="loginForm.get('password').valid || loginForm.get('password').untouched">Password is required</div> </div> <button type="submit" [disabled]="!loginForm.valid">Submit</button> </form>
- Add a method
onSubmit()
toFormComponent
class. - Bind the submit event to method in template
(submit)="onSubmit()"
- Import
HttpClientModule
toFormModule
so we can useHttpClient
:import { HttpClientModule } from '@angular/common/http';
- Note: Can also use
HttpModule
though it's deprecated.
- Note: Can also use
- Create a
FormService
to abstract out handling of Ajax calls:- Run
ng g s form/form --module=form
to scaffold service - Import
HttpClient
to make GET request to mock backend server "https://jsonplaceholder.typicode.com/users/1" - Return observable stream that
FormComponent
will subscribe to
import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; ... constructor(private httpClient: HttpClient) { } public login(username: string, password: string): Observable<any> { return this.httpClient.get('https://jsonplaceholder.typicode.com/users/1'); }
- Run
- Display the data from observable stream in template using
async
andjson
pipes:- Add property
user$
of typeObservable<any>
toFormComponent
class. - In
FormComponent
'sonSubmit()
method, setthis.user$
to returned value ofFormService.login()
:
public onSubmit(): void { const username = this.loginForm.get('username').value, password = this.loginForm.get('password').value; this.user$ = this.formService.login(username, password); }
- In template of
FormComponent
unwrap result of observable withasync
andjson
pipes:<p [hidden]="!user$">{{ user$ | async | json }}</p>
- Add property
- CSS freestyling on FormComponent!
- Component for navbar
- CoreModule for navbar, FormService
- SharedModule for CommonModule
- Maybe make login a promise since login isn't a good example for Observables.
- Write unit tests and e2e tests
- Etc
This project was generated with Angular CLI version 1.4.5.
Run ng serve
for a dev server. Navigate to http://localhost:4200/
. The app will automatically reload if you change any of the source files.
Run ng generate component component-name
to generate a new component. You can also use ng generate directive|pipe|service|class|guard|interface|enum|module
.
Run ng build
to build the project. The build artifacts will be stored in the dist/
directory. Use the -prod
flag for a production build.
Run ng test
to execute the unit tests via Karma.
Run ng e2e
to execute the end-to-end tests via Protractor.
To get more help on the Angular CLI use ng help
or go check out the Angular CLI README.