0

It's stated everywhere that you can pass data from parent to child either via @input or via a service. We have a policy to always use a service, but in this particular case I only know how to implement it with @Input. This code works perfectly for my intentions:

Parent - component.html

<ul>
  <li *ngFor="let item of items">
    <app-item [item]="item"></app-item>
  </li>
</ul>

Child (app-item) - component.ts

@Input() item: Item = {price: 0; size: 0; color: 'none'};

How can I change the child, so that the data will come from a service instead? I know how to do it 'onClick', but not how to do it when there are no user actions involved on the parent, just bare displays of lists (for other reasons, the parent and child have to be separate components).

The only way I can imagine this would work (but it's a teribble idea), if on each iteration on parent, I'd do something like subject.next(item). Any idea would be very much appriciated, I'm completely lost at what I should do.

Mandy
  • 107
  • 1
  • 2
  • 9
  • `subject.next(item)` That's how you do it. – Maihan Nijat Aug 29 '19 at 15:44
  • Is 'onClick' present in child? – Adrita Sharma Aug 29 '19 at 15:48
  • But where do I put this? Sorry, I know it must be a stupid question, but I'm very new to Angular. – Mandy Aug 29 '19 at 15:48
  • No, 'onClick' is not present, maybe it will be when the app grows, but right now its not. – Mandy Aug 29 '19 at 15:51
  • 1
    I sort of have the feeling, that you might have misunderstood the intention of your supervisor or whathaveyou. You did a plenty perfect implementation. Input works the best in this constellation, because while you can render the component with the *ngFor you cannot know which component gets which set of data. If they forbid the use if the @Input directive, they basically should give up on developing with Angular – ak.leimrey Aug 29 '19 at 16:07
  • Yes, it's quite possible that I have misunderstood it, it wouldn't be the first time:) Thank you very much for your help! – Mandy Aug 29 '19 at 16:32

1 Answers1

4

Edit: After clarification of the question, your best choice is @Input() decorator. The data is coming from the API and changes for each component, therefore, using service is not a good idea. Go with what you have and convince your supervisor.

Create a service:

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

@Injectable()
export class MyService {

  item = new BehaviorSubject<any>(null);

  constructor() {
  }
}

Import the above service to both you Parent and Child components. The parent component updates the value and the child component observe it.

In the parent where ever you need to update:

this.myService.item.next('Pass this data to the child');

And in the child subscribe to it:

this.myService.item.subscribe(data => this.data = data);

In the both parent and child components:

constructor(private myService: MyService) {}

And make sure you unsubscribe in ngOnDestroy().

Maihan Nijat
  • 9,054
  • 11
  • 62
  • 110
  • Thank you very much for your anwser! The problem I have though is that I listen to the `items` in the parent component - they come in as an observable (http call) and I subscribe to it. The only place I iterate through them is in the parent component.html and I don't know how to handle this list of items that comes as a stream (besides subscribing to it and then looping through it in html). Any suggestions perhaps? – Mandy Aug 29 '19 at 15:59
  • With my limited knowledge, I can only imagine to do this: ```
    ```
    – Mandy Aug 29 '19 at 16:00
  • @Many are you passing the items in iteration? – Maihan Nijat Aug 29 '19 at 16:01
  • 1
    @Mandy I guess your best bid is `@Input` decorator if you are looping through items and data is different for each component. – Maihan Nijat Aug 29 '19 at 16:07
  • I'm not sure I understand the question, but I think I am - in html I iterate through items (items are a result of a subscription in the parent). Is that what you mean? – Mandy Aug 29 '19 at 16:10
  • 1
    @Mandy I got your question. The service is really not a good solution for this case. Please go a head with `@Input()` – Maihan Nijat Aug 29 '19 at 16:11
  • I think so too, because it all works fine with @Input, but unfortunatelly I have to use a service and have no idea how to do it. – Mandy Aug 29 '19 at 16:12
  • Thank you very much again, I'll try to!! – Mandy Aug 29 '19 at 16:13