Home > Blockchain >  Data propagation on singleton services
Data propagation on singleton services

Time:11-25

I'm currently working with unrelated components and one shared service. Basically, one component will render all the items from an array inside the service and the other one will render the length of that array.

I don't know if I misunderstood the concept of singletons:

A singleton service is a service for which only one instance exists in an application.

But I was confused about something. Currently, my service looks like this:

@Injectable({
  providedIn: 'root',
})
export class DataService {
  data: IData = {
    items: [`initial item`],
  };
  constructor() {}

  addItem(item: string): void {
    this.data.items.push(item);
    console.log(`Item added!`);
  }
}

Right here I expect a single instance of this service and what I was trying to do is, creating a component with a button to add a New Item and I was expecting that the other component to refresh whenever that happened. I know that there's Subject and BehaviourSubject but if you look at this question: Is frequent use of BehaviorSubject in Angular services a red flag? you will understand that I cannot use a behavior subject to maintain the state of my data variable within my service.

That's why I opted to implement a singleton hoping that the data propagation would work as the next() and subscribe() from the RxJS behavior subject.

The main question would be: Is it possible to propagate the data using a singleton service?

This example will be provided within a stackblitz link below. I have two unrelated components:

Component for items:

<div>
  <div *ngFor="let item of items">
    <span>{{ item }}</span>
  </div>
  <button (click)="addNew()">Add New Product</button>
</div>

Component for the length of items:

<p>
  Total of items: {{ amount }}
</p>

Both of these components have an injection to access the same service in their constructors:

constructor(private dataService: DataService) { }

And one component that gathers them both:

<app-items></app-items>
<app-counter></app-counter>

This main component also has a provider on it.

@Component({
  selector: 'app-services',
  ...
  providers: [DataService]
})

Since this component gathers both of the others, I thought that putting the provider here would help me to accomplish what I wanted to get.

I also specified within the app-routing.module.ts the parent and the children.

{
    path: 'services',
    component: ServicesComponent,
    children: [
      {
          path: '',
          component: ItemsComponent,
      },
      {
          path: '',
          component: CounterComponent,
      }
  ]}

Adding a new item from the Items Component will not refresh the length of items on the other component. Is it possible to do that without using an event emitter or behavior subject and only a singleton?

All this example is here, a stackblitz, if want to take a look at a testing example.

CodePudding user response:

It could be done, bind the length directly to the UI through Interpolation.

<p>
Total of items: {{ cartService.cart.products.length }}
</p>

What you have done:

      ngOnInit() { // runs only once during initilization 
        console.log(`cartLL`, this.cartService.cart);
        this.amount = this.cartService.cart.products.length; 
        // pass by value not reference so it is only updated once
      }
  • Related