Linguine Code

A beginners guide to Angular services

In a recent article, What is an Angular component and how to use it, I mentioned that I’m coming from a React world.

Due to work, I’ve had to dabble my hands with Angular. So here comes another question that came to mind when beginning Angular.

How the heck do I save state in Angular?!

I came to found out, that Angular state is not like React state but more like React redux or React Mobx.

Angular state is called a service.

Before I can explain what an Angular service is, I have to ask the question, What design pattern does Angular use? because there is so much abstraction!

Angular is not an MVC pattern, It’s a MVVM design pattern

If you’re not familiar with MVC design pattern, here’s a quick overview:

M is for model

These types of files have 3 jobs. They’re meant to store, share, and manipulate the data to a format that the view would like.

V is for view

These file are literally the HTML files, or the files that generate UI components.

C is for controller

These types of files, are the middleman between the model and views.

A view makes a request to the controller, which the controller file lets the model know what the request is. Than the model returns some response (good, or bad news) to the controller which than lets the view know what to display.

So what does MVVM stand for?

MVVM stands for Model, View, ViewModel. Huh? Exactly!

In my Angular component article, I demonstrate the view, and the view model portion.

The HTML template file is my view, and my component.ts file is my view model.

The purpose of an Angular component is to present data and delegate data access to a service.

Service files are my models in Angular!

What does an Angular service do?

An Angular service primary job is to share data, and transform into something an Angular component can use.

Now let’s see how to create, and use a service in Angular.

Quick overview

I’m going to pick up from a recent example of creating an Angular component.

Just to give a quick recap of what I did previously.

I created 2 simple components.

  • Main app component
  • Greet component

And a Angular module file that specifies it can use the 2 Angular components listed above.

Here’s what I’m going to add to this:

  • Create person.service.ts – Will hold data about me, and will be able to manipulate the data with a few methods.
  • Update app.module.ts – Need to let the app know it can use this service in my components.
  • Update app.component.ts – The greet message will now be stored as a property and it will use the person service code to finish the greet message sentence.
  • Update app.component.html – Will be replacing the hard coded message and use the component property value.

Creating a Angular service


import { Injectable } from '@angular/core';

@Injectable()
export class PersonService {
  private firstName: string = 'Ruben';

  getFirstName(): string {
    return this.firstName;
  }

  changeFirstName(name: string): void {
    this.firstName = name;
  }
}

To make this file work properly, we must import the Injectable() decorator from angular core, and attach it to our class.

In my PersonService class, I’ve added a property named, firstName with a default string value of “Ruben”. That’s me!

This service has methods to help get the first name value, and change the first name value.

Inject service into module

The second step to this process is to let your App module know that it can even use this service.

If you try to use it without letting your app.module.ts know about it, Angular will get upset and break.

Updating the app.module.ts file.


// Import PersonService
import { PersonService } from './person.service';

@NgModule({
  // ... Other configurations
  providers: [PersonService],
})
export class AppModule {}

In this file, I’m importing my PersonService class, and adding into my NgModule() configuration.

The NgModule() configuration has a property called, providers. This property accepts an array of Injectable() objects, such as the service that was created above.

Using the service in a Angular component

Now that we let the Angular app know that it can use this service. The next step is to actually use it in the component file.

I will hop over to my app.component.ts file and code to it. Originally, this file was an empty class. Now,


import { Component, OnInit } from "@angular/core";
import { PersonService } from './person.service';

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {

  greetMessage: string;

  constructor(private person: PersonService) {}

  ngOnInit() {

    // Hi there, my name is Ruben
    this.greetMessage = `Hi there, my name is ${this.person.getFirstName()}`;

    // In 2 seconds, change the first name
    setTimeout(() => {

      // Changing the first name
      this.person.changeFirstName('John');

      // But people call me John
      this.greetMessage = `But people call me ${this.person.getFirstName()}`;
    }, 2000);
  }
}

That’s a lot of additional code. Let’s go over a code breakdown.


import { Component, OnInit } from "@angular/core";
import { PersonService } from './person.service';

export class AppComponent implements OnInit {
   // ... code
}

The first couple things I’m doing is importing the OnInit class from the Angular core files, and my custom service, PersonService.

I’m also implementing OnInit to my AppComponent class. This will provide a method called, ngOnInit().

ngOnInit() is the equivalent to React’s componentDidMount() lifecycle.

Anything that has to do with data fetching or manipulating, is best to do it when the component has mounted.


greetMessage: string;

constructor(private person: PersonService) {}

The next chunk of code is fairly simple. I’m creating a greetMessage property, and I’m injecting my person service class inside the constructor signature method.

Inside the ngOnInit() method, that’s where I’m utilizing my service.


ngOnInit() {

  // Hi there, my name is Ruben
  this.greetMessage = `Hi there, my name is ${this.person.getFirstName()}`;

  // In 2 seconds, change the first name
  setTimeout(() => {

    // Changing the first name
    this.person.changeFirstName('John');

    // But people call me John
    this.greetMessage = `But people call me ${this.person.getFirstName()}`;
  }, 2000);
}

When my Angular component has mounted, I’m giving the greetMessage property and default value with the default firstName value in my person service.

I’m then setting a command, to change the first name to John, and change the greetMessage value, 2 seconds after the component has mounted.

Now that the logic has been implemented, all that’s left is to make the HTML use this dynamic variable value.

Reference variable from Angular component to HTML template


// Previous code
<greet message="Hi there, my name is Ruben."></greet>

// New code
<greet [message]="greetMessage"></greet>

By wrapping the message input with brackets, you let Angular know that it referencing a variable and not a raw value.

Conclusion

Now that you’ve created your service, any components defined in your module file, using the service will stay in sync with the data.

Coming from a React state world to Angular services, can seem convoluted and mundane. But when you think about it, it makes sense why the Angular team has structured this way.

Stay tuned to check out my thoughts on React vs Angular next!

GitHub source link