ored95 / AngularSeven

The Complete Guide to Angular 7

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

AngularSeven

The Complete Guide to Angular 7

Part 1. First command to test app

    ng serve

This command helps testing easily our app locally while developing. See more about the Angular CLI here.

Import "Typescript" form feature to store the input in into the "name" property by using this syntax below:

    [(ngModel)]="name"

Install locally bootstrap and make clean start project:

    npm install --save bootstrap@3

Part 2. Components

Generate new components:

    ng generate component servers

After a bit changes, we get these html tag codes like that

<body>
    <app-root>
        ...
        <app-servers>
            <app-server></app-server>
            <app-server></app-server>
        </app-servers>
    </app-root>
    ...
</body

Two ways to use data binding:

  1. Using $event:
    <input
        type="text"
        class="form-control"
        (input)="onUpdateServerName($event)">
  • And the main script:
    onUpdateServerName(event: Event){
        this.serverName = (<HTMLInputElement>event.target).value;
    }
  1. Using ngModel:
  • It should be the better method by it's simplicity. First, we need to add the FormsModule:
    //app.module.ts
    import { FormsModule } from '@angular/forms'
  • Then, easy stuff is remaining like that:
    <input
        type="text"
        class="form-control"
        [(ngModel)]="serverName">

If-else statements:

    <p *ngIf="serverCreatedFlag; else noServer">Server {{ serverName }} was created successfully!</p>
    <ng-template #noServer>
        <p>No server was created.</p>
    </ng-template>

How to dinamically change style of element:

  1. Using ngStyle:

    This method allows us to dynamically assign a style itself.

    <p [ngStyle]="{backgroundColor: getBackgroundColor()}"></p>
  1. Using ngClass:

    This method allows us to dynamically add or remove CSS-classes.

    <p 
        ...
        [ngClass]="{online: getServerStatus() === 'online'}"
    ></p>
  1. Using ngFor:

    It would be nicer to have an array of service which adds them dynamically like that:

    <app-server *ngFor="let server of servers"></app-server>

Part 3. The Basics

Recommend using Bootstrap 3+

  • Why Bootstrap 3? See this issue.
  • Take a look at styling Angular 7 using Bootstrap 4+ here

Header

  • See more how navigation work here.

Body

  1. Adding styles to gird our body after header
    body {
        min-height: 2000px;
        padding-top: 70px;
    }
    
    .btn-space {
        margin-right: 5px
    }
  1. Adding Models

    • Recipe (name, description, imagePath)
    • Ingredient (name, amount)

Part 3. Debugging

  1. Using Augury to dive into our Angular Apps.

  2. Assigning an Alias to custom properties:

    @Input('srvElement') element : {type: string, name: string, content: string};
  1. Binding to custom events
    <app-server 
        (serverCreated)="onServerAdded($event)"
        (blueprintCreated)="onBlueprintAdded($event)">
    </app-server>
  • Now, let's see how to emit an object in Angular
    import { EventEmitter, Output } from '@angular/core';

    @Output() serverCreated = new EventEmitter<{serverName: string, serverContent: string}>();
    
    newServerName = ''
    newServerContent = ''

    onServerAdded() {
        this.serverCreated.emit({
            serverName: this.newServerName,
            serverContent: this.newServerContent
        });
    }
  • Here, the method onServerAdded() is also declared in other script file (up/down level)
    serverElements = [];

    onServerAdded(serverData: {serverName: string, serverContent: string}) {
        this.serverElements.push({
            type: 'server',
            name: serverData.serverName,
            content: serverData.serverContent
        });
    }
  • How to listen from outside?
    @Output('bpCreated') blueprintCreated = new EventEmitter<{serverName: string, serverContent: string}>();
  • Using Local References in Templates
    <input
        type="text"
        class="form-control"
        #addedServer>
    <button
        class="btn btn-primary"
        (click)="onServerAdded(addedServer)">Add Server</button>
    onServerAdded(addedServer: HTMLInputElement) {
        this.serverCreated.emit({
            serverName: addedServer.value,
            serverContent: this.newServerContent
        });
    }
  1. Lifecycle
  • ngOnChanges - called after a bound input property changes
  • ngOnInit - called once the component is initialized
  • ngDoCheck - called during every change detection run
  • ngAfterContentInit - called after content (ng-content) has been projected into view
  • ngAfterContentChecked - called every time the projected content has been checked
  • ngAfterViewInit - called after the component's view (and child views) has been initialized
  • ngAfterViewChecked - called every time (and child views) have been checked
  • ngOnDestroy - Called once the component is about to be destroyed

Part 4. Services Dependency Injection

  1. Setting up the Services
    // recipe.service.ts
    import { Recipe } from './recipe.model';

    export class RecipeService {
        
        private recipes: Recipe[] = [<recipes>]

        getRecipes() {
            return this.recipes.slice();
        }
    }
  1. Using a Service for Cross-Component Communication
    export class RecipeListComponent implements OnInit {
        recipes: Recipe[];

        constructor(private serviceRecipe: RecipeService) { }

        ngOnInit() {
            this.recipes = this.serviceRecipe.getRecipes();
        }
    }
  1. Using Services for Push Notifications
    //shopping-list.component.ts
    ingredients: Ingredient[];

    constructor(private serviceSL: ShoppingListService) { }

    ngOnInit() {
        this.ingredients = this.serviceSL.getIngredients();
        this.serviceSL.ingredientChanged.subscribe(
            (ingredients: Ingredient[]) => {
                this.ingredients = ingredients; 
            }
        );
    }
  1. Passing Ingredients from Recipes to the Shopping List (via a Service)
    //recipe.service.ts
    import { Recipe } from './recipe.model';
    import { EventEmitter, Injectable } from '@angular/core';
    import { Ingredient } from '../shared/ingredient.model';
    import { ShoppingListService } from '../shopping-list/shopping-list.service';

    @Injectable()
    export class RecipeService {
        // ...
        constructor(private serviceSL: ShoppingListService) {}
        
        getRecipes() {
            return this.recipes.slice();
        }

        addIngredientsToShoppingList(ingredients: Ingredient[]) {
            this.serviceSL.addIngredients(ingredients);
        }
    }

Part 5. Forms, Controls and Validations

Note: See all changes in two previous commits!

Part 6. Http requests

  1. Introduction to Firebase: Store and sync data in real time

  2. Tutorial: Angular 7|6 By Example: HTTP GET Requests with HttpClient (Services, async pipe and Observables)

  3. Part of project

  • Setting up HttpClient:
    //app.module.ts
    import { HttpClientModule } from '@angular/common/http';

    imports: [
        BrowserModule,
        FormsModule,
        AppRoutingModule,
        ReactiveFormsModule,
        HttpClientModule
    ],
  • Sending PUT Requests to Save Data:
    //data-storage.service.ts
    import { Observable } from 'rxjs';

    /** PUT: update the recipes on the server. Returns the updated recipes upon success. */
    storeRecipes() : Observable<Recipe> {
        return this.http.put<Recipe>(this.dbURL, this.recipeService.getRecipes());
    }
    //data-storage.service.ts
    /** GET: Fetch the recipes on the server. Returns the sync recipes upon success. */
    getRecipes() {
        this.http.get<Recipe[]>(this.dbURL)
            .subscribe(
                (response) => {
                    this.recipeService.setRecipes(response);
                }
            );
    }

Part 7. Authencation

  1. Install firebase
    npm cache clean --force
    npm install --save firebase
  1. Setting up signin and signup routes
    //app-routing.module.ts
    { path: 'signup', component: SignupComponent },
    { path: 'signin', component: SigninComponent },
  1. Authencation

    Let's see an example of sign in authencation

    signinUser(email: string, password: string) {
    firebase.auth().signInWithEmailAndPassword(email, password)
        .then(
            response => {
            this.router.navigate(['/']);
            firebase.auth().currentUser.getIdToken()
                .then(
                (token: string) => this.token = token
                )
            }
        )
        .catch(
            error => console.log(error)
        );
    }
  1. Authencation to Route protection
    import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';

    @Injectable()
    export class AuthGuard implements CanActivate {

        constructor(private authService: AuthService) {}

        canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
            return this.authService.isAuthenticated();
        }
    }
  • Here, user can only be activated when they have their own token:
    isAuthenticated() {
        return this.token != null;
    }
  1. Redirection and Wrap up
    // For a test
    Email: test@test.com
    Password: 123123

About

The Complete Guide to Angular 7

License:MIT License


Languages

Language:TypeScript 70.5%Language:HTML 21.2%Language:JavaScript 7.3%Language:CSS 0.9%