Skip to content

Latest commit

 

History

History
426 lines (364 loc) · 14.5 KB

angular.md

File metadata and controls

426 lines (364 loc) · 14.5 KB

Angular

CLI

  • ng serve --port <port no> --host <host name>
  • ng g c mymodule/<component name> -m <module name>
  • ng g m <module name> --routing
  • -d reports actions without writing results.
  • -it inline template
  • -is inline css
  • --style= css|scss|sass|less|styl
  • -S do not create spec files
  • --flat=true do not create a folder
  • -c OnPush change detection strategy
  • ng add
    • adds npm package to your workspace
    • and configures the project to use that library
    • as specified by the library's schematic.

Decorators

Metadata about the actual code

@component

https://angular.io/api/core/Component

@NgModule

  • imports
    • to import another modules to use.
  • declarations
    • Declares what is inside this module (Components, Pipes)
  • bootsrap
    • Which componet is the first one that should displayed in the UI. I.e., the startup component
  • exports
    • Make sure anyone else imports this module, gets access to these exported components.
  • providers
    • providing services (like exporting components)
    • any modules that load under the root module, will have access to the providers (publicly available)

@Injectable()

dependency injection in angular. https://angular.io/api/core/Injectable

Components

Oninit

  • ngOnInit The place where we initialize the component with data

Modules

Group of related components.
Any components need to be declared in a module.
The root module needs to know about child modules.
Make a shared module if you have shared features e.g., components, pipes, directives, that you may reuse throughout the app.

Angular modules

Directives

Data Binding

Get data moved from code into tamplate and also handle events.

  • interpolation to write a value
    • {{ x.name }}
  • property binding
    • binding to a DOM property
    • [hidden]="!isVisible"
    • [disabled]="!isEnabled"
    • [class.active]="isActive"
    • [style.color]="textColor"
    • [innerHtml]="details"
      • the same as {{ details }}
  • event binding
    • (click)="toggleVisible()"
      • or on-click="toggleVisible()"
  • Two-way binding
    • [(ngModel)]="post.title"
      • it will also handle input event and update post.title

Input property

a way to pass a property value into a child component. make the child accepts input form the parent. get data from a parent down into a child

  • Use ngOnChanges if we have a lot of properties we want to monitor when that data changes for these props,
    @Input() data: Any[];
    ngOnChanges(changes: SimpleChanges) {/* check for changes*/}
    // https://angular.io/api/core/OnChanges
  • getters and setters another technique that can be used if we only have one property to check
    // child.component.ts
    
    private _posts: Post[] = [];
    // only put the @Input() decorator on one of (get or set)
    @input() get posts(): Post[] { return this._posts; }
    
    // a way to capture when it is being set to value
    set posts(value: Post[]) { 
      if(value) {
        _posts = value;
         /* do something */
      }
    }
    <!-- parent.component.html -->
    
    <app-posts [posts]="blogPosts"></app-posts>

output property

emit data from a child back up to a parent.

  • EventEmitter<T> a way for a child to send data to a parent
// child.component.ts

@Component({
  selector:'app-search',
  template:`
    // <input type="text" [value]="search" (input)="$event.target.value />
    <input type="text" [(ngModel)]="search name="search"" /> <!-- Easier way. from FormsModule --> 
  `
})

private _search: string;

get search() { return this._search }

set search(value: string) {
  this.value = value;
  this.changed.emit(this.search); // emit search value up to the parent
}

@output changed = new EventEmitter<string>();
<!-- parent.component.html  -->

<!-- angular automatically extract the data from $event and pass it to the function -->
<app-search (changed)="myFun($event)"></app-search>

Local Templates <ng-template>

Local template variable: With it, we can reference a particular DOM element in the rest of the component template.

  <h1 *ngIF="selection; else elseBlock">{{selection}}</h1>
  <!-- a way to declare a local template variable is by using (#) #myVar -->
  <ng-template #elseBlock>Please select</ng-template>

Pipes

Format the data as we bind it out to the UI.

built-in pipes

https://angular.io/api?type=pipe

  • price | currency:'USD':<'symbol', 'code'>
    • if currency code is not passed, the browser default will be used

Build a custom pipes

we need

  • @Pipe({ name: echo}) decorator
    • name which you use in the view
  • implement PipeTransform interface
    • implement transform(value: any){ return value; } function
  • register it in a module
    • declarations: [EchoPipe], exports: [EchoPipe]

Forms

When dealing with a form, start with an empty object that you can bind to, until you have a selected object that you're going to edit.

Template forms versus reactive forms -> https://angular.io/guide/forms-overview#choosing-an-approach

Template forms

create a local template variable =ngForm

  • When we create a form element, Under the hood,
    • Angular will create a form control to monitor what is happening with the form
    • (keep track of the values of the form and valid state of it)

When using a submit button, bind to the form submit event <form (sumbit)="save()">,
instead of binding to that button click event.

Services

A singleton. Introduction to services and dependency injection

Dependency Injection

Inject services into components. https://angular.io/guide/dependency-injection
Instruct Angular to inject the dependencies of a component into its constructor.

When we set an access modifier on a parameter in a constructor of a class, TypeScript will automatically assign it to a memebr of that class.

HTTP

Calling the server with HttpClient. https://angular.io/guide/http

HTTPClient

https://angular.io/api/common/http/HttpClient

Observables

Pipe and operators

  • catchError
    • put catchError(myErrorHandler) operator inside .pipe() to handle errors
  • map, reduce
    • We can operate, select, filter, the response data.
  • debounceTime
  • takeUntil
  • Common operators
// DataService.ts

@Injectable()
export class DataService {
  constructor(private http: HttpClient) {}

  getData(): Observable<any[]> { 
    return this.http.get<any[]>('data/')
      .pipe(
        map(data => data.rows || []),
        catchError(Observable.throw)
      );
  }
}
// component.ts

data: any[];

constructor(private dataService: DataService) {}

ngOnInit() {
  this.dataService.getData()
    .subsrcibe((data: any[]) => this.data = data);
}

Routing

Routes Interface

[ Optinal ] helps us avoid typos as we define our routes.

  • path
    • path: '' match the root of the website
    • path: '**' match anything
  • pathMatch
    • pathMatch: 'full' match on everything after the domain
  • redirectTo
    • redirectTo: '/app-route'
  • component
    • { path: 'products', component: ProductsComponent }
  • pass data to the component
    • //producs-routing.module.ts
      
      const routes: Routes = [
        { path: 'products', component: ProductsComponent, data: {...data} }
      ];
    • // products.component.ts
      
      data$: Observable<any>;
      
      constructor(private route: ActivatedRoute) {}
      
      ngOnInit() {
        this.data$ = this.route.data;
      }

RouterModule

To register routes

  • imports: [ RouterModule.forRoot(myRoutes) ]
    • forRoot is called one time in the app.
  • imports: [ RouterModule.forChild(routes) ] another option for children.

ActivatedRoute

Use it to get URL/query parameters.

  • paramMap
    • to subscribe to the parameters. It would notify us any time that the ParamMap changes.
    • Tip: Can be used if our components stay visible on the screen while the URL changes.
  • snapshot.paramMap
    • If we want to grap the parameter once.

RouterLink

Use with anchor tags <a> to link to a route.

  • <a [routerLink]="['/orders', order.id]">{{order.title}}</a>
    • ['/orders', order.id] mapped to '/orders/:id'
  • routerLinkActive="css-class"
    • Detect and attach a CSS class to the element that is attached to the active route.

Navigate using the Router service

  // header.component.ts

  // template: `<button (click)="logout()">Logout</button>`
  
  constructor(private router: Router) {}

  logout() {
    // logic
    this.router.navigateByUrl('/login');
  }

Lazy Loading

  • RouterModule. forRoot(myRoutes) vs forChild(myRoutes)

    • We want to have only a single routing service to handle the application routes
    • foorRoot will load the routing service besides all of the routes.
    • Inside child routing modules, for lazy loading childs, we want to use forChild,
      because it is not going to load the routing servive, so we won't to override the routing service.
  • loadChildren: Creating a separate bundle for a particular module and lazy loading it into the application

    • use loadChildren, it performs asynchronous call to load whatever we give to it. e.g., a module
        // app-routing.module.ts -> root routing module
        const routes: Routes = [
          { /*route 1*/ },
          { path: 'user', loadChildren: () => import('./user.module').then(module => module.UserModule) },
          // {...},
        ];
        // user-routing.module.ts -> child routing module
      
        // NOTE: paths here will be relative the the parent (root) routing module.
        // And every child inside this (user) routing module will treat it as its root
        const routes: Routes = [
          { path: '', component: UserComponent },
        ];

Deep Dive