Sharing Data Between Components Using Service in Angular
Sharing Data Between Components Using Service in Angular

In this video you will learn about sharing data between components using service in Angular. We can of course just write our API call inside component but then we can't really reuse this code because it's coupled with a component. Services in Angular help us to share data between different components in an easy and dry way.

In previous video we made our first API call to our fake json-server. If you didn't see that video go check it now. It works all fine but we have 2 problems here. First, if we want to fetch users in other place we need to write this code again. And second our component knows now too much. It has not only view logic but all logic fetch logic. And it will be even worse when we add here delete and add API calls.

This is why we have services in Angular. So what is services? Nothing difficult. It's just a class with methods. We can inject it in different components and reuse methods from it. It's not only related to working with API. we can put there any logic that we want.

Let's try to move getting of users to the service first. First we need a service folder in app.

users.service.ts

import {Injectable} from '@angular/core'

@Injectable()
export class UsersService {
  foo(): string {
    return 'foo'
  }
}

So here we created basic UsersService. The most important part here is Injectable. It will give us possibility to use this class inside Angular. What is more important is round brackets because without them you will get really magic errors.

Now let's try to add use it inside our app.component.

constructor(private http: HttpClient, private usersService: UsersService) {}

ngOnInit(): void {
  console.log(this.usersService.foo())
}

In browser now we get an error

No provider for UsersService!

because we didn't bind our Service to the module. To do that we need to add our service to providers list of the module where this component is declared.

@NgModule({
  ...
  providers: [UsersService],
  ...
})
export class AppModule {}

Now we don't have any errors and we see foo in browser. Let's move how getting to the service.

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

  getUsers(): Observable<UserInterface[]> {
    return this.http.get<UserInterface[]>('http://localhost:3000/users')
  }
}

Now it may be complicated. So we want to say what we are getting back. And this thing what htt.get gives us where we can use subscribe later is called Observable. Inside Observable in tags we can specify what type of data use are getting back. The problem here is that this.http.get gives back in typings Observable Object and we need to manually tell Typescript what we get back. This is why this code looks a bit verbose.

Now we can use getUsers function inside our component.

this.usersService.getUsers().subscribe((res: UserInterface[]) => {
  this.users = res
})

As you can see, everything is working exactly as before but now our communication with API is inside service and we can reuse it everywhere. Also our component doesn't know anything about fetching from API. It just knows that there is a stream which give correct data back.

Let's make a removing API call also now.

removeUser(id: string): Observable<{}> {
  return this.http.delete(`http://localhost:3000/users/${id}`)
}
removeUser(id: string): void {
  this.usersService.removeUser(id).subscribe(() => {
    this.users = this.users.filter((user) => user.id !== id)
  })
}

Here we created one more method inside our service and called it inside removeUser with subscribe. In this case we are sure that first we get the successful response and only then we change our UI.

addUser(name: string, age: number): Observable<UserInterface> {
  return this.http.post<UserInterface>('http://localhost:3000/users', {
    name,
    age,
  })
}
addUser(userName: string): void {
  this.usersService.addUser(userName, 30).subscribe((res: UserInterface) => {
    this.users.push(res)
  })
}

Here we created a new addUser post method and passed correct data from our component.

As you can see now we don't need to generate ID because we get it from API and everything is working in the same way.

In this video you learned on the real example how to write services in Angular. And of course you can write any functions or variables inside services and not just API calls.

If angular for beginners is too easy for you or you want more advanced stuff check my 14 hours Angular course where we create a real project from beginning to the end. Link is also in the description.

📚 Source code of what we've done