Menu Search Me

Angular Models and Services

Models

How to define a model?

You can use the ng tool to generate an empty model. In the below example, the models are defined under the src/app/core/models folder:

src/app/core/models/

ng generate class Hero

src/app/hero.ts

export class Hero{
    constructor(
        public id: number,
        public name:string,
        public power:string,
        public alterEgo?:string
    ){}
}

Note in above example the use of question mark (?) in alterEgo?: The alterEgo is optional, so the constructor lets you omit it.

You can create a new hero like this:

let myHero =  new Hero(42, 'SkyDog',
                       'Fetch any object at any distance',
                       'Leslie Rollover');
console.log('My hero is called ' + myHero.name); // "My hero is called SkyDog" 

Let us look at another example. In the below example, all models are defined in src/app/shared/models. Below is an example model "ImmunizationRecordSubmission", in a file "ImmunizationRecordSubmission.model.ts":

import { ImmunizationAdministrator } from './ImmunizationAdministrator.model';

import { ImmunizationEvent } from './ImmunizationEvent.model';

import { SUBMISSION_STATUS } from '../../app.settings';

import { Recommendation } from './Recommendation';

import { Submitter } from './Submitter.model';

import { Patient } from './Patient.model'; 

export class ImmunizationRecordSubmission {

  submitter: Submitter = null;

  patient: Patient = new Patient();

  immunizationAdministrator: ImmunizationAdministrator = new ImmunizationAdministrator();

  retrievedImmunizations: ImmunizationEvent[] = [];

  newImmunizations: ImmunizationEvent[] = [];

  recommendations: Recommendation[] = [];

  referenceNumber: string = null;

  id?: number;

  status?: SUBMISSION_STATUS; 

  clearRecord() {

    this.patient = new Patient();

    this.immunizationAdministrator = new ImmunizationAdministrator();

    this.retrievedImmunizations = [];

    this.newImmunizations = [];

    this.recommendations = [];

    this.referenceNumber = null;

  }

} 

Note that in the above model example, a function (clearRecord()) is defined for the model.

Also note that in above examples, the ? question mark means the variable is optional. 

If you want to define a constructor for your model, here is another example:

/**

 * Contains the barcode information retrieved while scanning

 */

export class BarcodeInfo {

  gtin: string;

  lot?: string;

  expiry?: string;

  serial?: string; 

  constructor (gtin: string, lot?: string, expiry?: string, serial?: string) {

    this.gtin = gtin;

    this.lot = lot;

    this.expiry = expiry;

    this.serial = serial;

  }

} 

In above examples, the ? question mark means the variable is optional. 

How to use another model in a model?

Take the Patient class defined in patient.model.ts for example. It uses the models Address and Guardian:

import { Address } from './Address.model';

import { Guardian } from './Guardian.model'; 

export class Patient {

  firstName = '';

  middleName? = '';

  lastName = '';

  phone = '';

  dateOfBirth: Date = null;

  healthCardNumber = '';

  oiid = '';

  gender: string = null;

  hasConsentBlock = false;

  address?: Address = new Address();

  guardians?: Array<Guardian> = [];

} 

Export: You always use the "export" keyword to make the model available for use by other models, services, components.

Import: For any models you want to use in this model, use the "import" statement to import them first.

How to use models in services and components? 

In the service & component where your model will be used, import the model:

import { ImmunizationRecordSubmission } from '../../shared/models/ImmunizationRecordSubmission.model'; 

Then you can just use the model in the functions of the services or components:

let immunizationRecord = new ImmunizationRecordSubmission(); 

It is basically the same as using models in another model.

Services

Service is a broad category encompassing any value, function, or feature that your application needs.

Almost anything can be a service. A service is typically a class with a narrow, well-defined purpose. It should do something specific and do it well.

Examples include:

  • logging service
  • data service
  • message bus
  • tax calculator
  • application configuration

Here's an example of a service class that logs to the browser console:

src/app/logger.service.ts (class)

export class Logger {
  log(msg: any)   { console.log(msg); }
  error(msg: any) { console.error(msg); }
  warn(msg: any)  { console.warn(msg); }
}

Here's a HeroService that uses a Promise to fetch heroes. The HeroService depends on the Logger service and another BackendService that handles the server communication grunt work.

src/app/hero.service.ts (class)

export class HeroService {
  private heroes: Hero[] = [];
  constructor(
    private backend: BackendService,
    private logger: Logger) { }

  getHeroes() {
    this.backend.getAll(Hero).then( (heroes: Hero[]) => {
      this.logger.log(`Fetched ${heroes.length} heroes.`);
      this.heroes.push(...heroes); // fill cache
    });
    return this.heroes;
  }
}

Here is a service function that uses the rxjs to notify the components when a response comes back from the web server:

  Userlogin(user: string, pass: string) : Observable<User[]> {
    let data = JSON.stringify({ username: user, password: pass }); // Stringify payload
    /*
    //simulating server ajax call
    return Observable.create(function subscribe(observer) {
      try {
        observer.next(JSON.parse("{\"username\":\"testuser\",\"status\": 0}"));
        
      } catch (err) {
        observer.error(new Error(`${err.status} ${err.statusText}`)); // delivers an error if it caught one
      }
    });
    */
    //connecting real service and get response back
    return (
      this.http
        .post(Authentication_URL, data, HEADER) // ...using post request
        .map((res: Response) => res.json()) // ...and calling .json() on the response to return data
        // .map(response => response.json().data as SuspendAckMsg[])
        .catch(e => {
          return Observable.throw(new Error(`${e.status} ${e.statusText}`));          
        })
    );
    
  }

Here is the component function that calls the above service function:

  Userlogin() {
    this.currentuser.username = this.model.username;
    this.currentuser.password = this.model.password;
    this.errorMessage = "Please wait....";
    this.authenticationService
      .Userlogin(this.model.username, this.model.password)
      .subscribe(
        Response => {
          //you have to stringify the response though it looks like a User[]
          this.FormatLoginAckMsg(JSON.stringify(Response));
          if (this.currentuser.code && this.currentuser.status == 0) {
            localStorage.setItem("currentUser", JSON.stringify(this.currentuser));          
            this.errorMessage = null;
            et link = ["/suspenddrain"];          
            this.router.navigate(link);
          } else {
            localStorage.removeItem("currentUser");
            this.errorMessage = "Invalid User Credentials";
          }
        },
        err => {
          this.errorMessage = err.message;
          console.error(err.message);
        },
        () => {
          console.log("Completed");
        }
      );
  }

  private FormatLoginAckMsg(data: string) {
    let jsonData = JSON.parse(data);
    console.log(jsonData.status);
    console.log(jsonData.code);
    this.currentuser.status =jsonData.status;
    this.currentuser.code = jsonData.code;
  }

Using service in another service

Here is an example service that uses 2 other services:

import { ImmunizationRecordService } from '../immunization-record/immunization-record.service';
import { LoggingService } from '../logging/logging.service';

......

constructor(private immunizationRecordService: ImmunizationRecordService, private loggingService: LoggingService) {
}

......

this.loggingService.logIspaVsNonispaImmunizationSubmission(this.submitter, imm);
this.newImmunizations = this.immunizationRecordService.getNewImmunizations();

Using service in Angular component

Reference: https://angular.io/guide/providers 

To create a service to be used in Angular components, use the following command to generate a skeleton service:

ng generate service User

This command creates the following UserService skeleton:

src/app/user.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class UserService {
}

You can now inject UserService anywhere in your application. Here is the example (here-list.component.ts):

import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

import { HeroService } from '../hero.service';
import { Hero } from '../hero';

@Component({
  selector: 'app-hero-list',
  templateUrl: './hero-list.component.html',
  styleUrls: ['./hero-list.component.css']
})
export class HeroListComponent implements OnInit {
  heroes$: Observable<Hero[]>;
  selectedId: number;

  constructor(
    private service: HeroService,
    private route: ActivatedRoute
  ) {}

  ngOnInit() {
    this.heroes$ = this.route.paramMap.pipe(
      switchMap(params => {
        // (+) before `params.get()` turns the string into a number
        this.selectedId = +params.get('id');
        return this.service.getHeroes();
      })
    );
  }
}

You do not have to specify "providers" in @NgModule or @Component.