ViewProviders In Angular

ViewProviders In Angular

In this article, We will learn about the ViewProviders. ViewProviders are identical to Providers, but the dependencies you set are only visible to the view children of the ViewProvider. The Content kids aren't able to see them.

ViewProviders Example

The app has a RandomService that, when initialized, creates a random number.

Open the random-service.ts file and add the following code

import { Injectable } from "@angular/core";
 
@Injectable({
  providedIn: "root"
})
export class RandomService {
  private _randomNo = 0;
 
  constructor() {
    console.log("RandomService Constructed");
    this._randomNo = Math.floor(Math.random() * 1000);
  }
 
  get RandomNo() {
    return this._randomNo;
  }
}

The RandomService's random no is displayed by the ChildComponent.

It also comes with ng-content, which allows the parent to insert content. The GrandChildComponent will be injected here by the Parent component.

GrandChildComponent is also displayed as View by ChildComponent.

Add the following code under the child.component.ts file 
import { Component, SkipSelf, Self, Optional, Host } from '@angular/core';
import { RandomService } from './random-service';
 
@Component({
  selector: 'my-child',
  providers: [],
  viewProviders: [],
  template: `
    <div class="box">
      <p>ChildComponent => {{ randomNo }}</p>
      <ng-content> </ng-content>
 
      <strong>View Child</strong>
      <my-grandchild></my-grandchild>
    </div>
  `
})
export class ChildComponent {
  randomNo;
  constructor(private randomService: RandomService) {
    this.randomNo = randomService.RandomNo;
  }
}

The RandomService's random no is displayed by GrandChildComponent. The @Optional() decorator ensures that if the dependency isn't identified, no error is produced.

Add the following code under the grand-child.component.ts file
import { Component, SkipSelf, Self, Optional, Host } from "@angular/core";
import { RandomService } from "./random-service";
 
@Component({
  selector: "my-grandChild",
  template: `
    <div class="box">
      GrandChildComponent => {{ randomNo }}
    </div>
  `,
  providers: [],
  viewProviders: [],
})
export class GrandChildComponent {
  randomNo;
  constructor(@Optional() private randomService: RandomService) {
    this.randomNo = randomService?.RandomNo;
  }
}

The ChildComponent is displayed in the AppComponent. We also use projected content to project the GrandChildComponent into the ChildComponent.

Now, open the app.component.ts file and put the following code
import { Component, VERSION } from '@angular/core';
import { RandomService } from './random-service';
 
@Component({
  selector: 'my-app',
  providers: [],
  viewProviders: [],
  template: `
    <div class="box">
    <div class="box">
      <p>AppComponent => {{ randomNo }}</p>
      <my-child>
        <strong>Projected Content</strong>
        <my-grandchild></my-grandchild>
      </my-child>
    </div>
 
 
  `
})
export class AppComponent {
  randomNo;
  constructor(private randomService: RandomService) {
    this.randomNo = randomService.RandomNo;
  }
}

When you run the app, you'll notice that the random number is assigned to all of the components. Because the RootModuleInjector provides the RandomService.

Also, the GrandChildComponent is displayed twice by ChildComponent. As a Content Child (Projected Content) and as a View Child at the same time.

Add the RandomService to the ChildComponent's Providers array. As you can see in the figure below, the RandomService provided by the ChildComponent is used by ChildComponent and all of its children (content children and view children).

The RandomService should now be moved from Providers to ViewProviders. View Child still receives the RandomService from ChildComponent, as shown in the image below, however Projected Content does not. The Root Module provides the service to Projected Content.

All children are welcome to access the services provided by the providers. Other than projected content, the viewProviders limit it to children.

Use case for ViewProviders

This is helpful when creating libraries.

For example, suppose you created some-great-comp that a user will use to project their user-component into.
<some-great-comp>
   <user-component></user-component>
</some-great-comp>

You don't want services from your some-great-comp to interfere with the user-component in this case. As a result, you offer your services through ViewProviders.

Conclusion

In this article, We learned about the ViewProviders in abguaar with example.

I hope this article helps you and you will like it.👍

If you have any doubt or confusion then free to ask in comment section.

Post a Comment

Previous Post Next Post