1

I have a ParentComponent with a ChildComponent that contains another ChildComponent(ResultList in a sidebar)

In the ParentComponent I open a dialog with a similar ResultList from the sidebar- technically it is the same component - but it has more items.I try to select some of the values in the dialog and then I want to push them to the first ResultList in the sidebar again.

Now I'm trying to pass the resultList variable to each component to get my list updated in the sidebar, but it seems a little bit complex.

If you (hopefully) unterstand my problem - Do you have any other ideas how can I update my sidebarcomponent from the modal dialog?

If you have further questions - please ask :)

3
  • I think some code samples would help clarify. You may want to have a look at angular.io/guide/component-interaction Commented Oct 25, 2018 at 13:49
  • 1
    Very hard to tell without any code, but your probably looking for a service Commented Oct 25, 2018 at 13:52
  • 1
    Why not use a Service with a BehaviorSubject exposed asObservable and subscribe to it in all the components where you want to get the updated resultList Commented Oct 25, 2018 at 14:25

4 Answers 4

12

I'd recommend using a Service with a BehaviorSubject exposed asObservable and subscribeing to it in all the components where you want to get the updated resultList

So you'll have a service:

import { BehaviorSubject, Observable } from 'rxjs';
...
export class ResultListService {
  private resultList: BehaviorSubject<any[]> = new BehaviorSubject<any[]>(null);
  public resultList$: Observable<any[]> = this.resultList.asObservable();

  updateResultList(updatedList) {
    this.resultList.next(updatedList);
  }
}

In the dialog component, you'll use the updateResultList method and pass it the updatedResultList:

constructor(..., private resultListService: ResultListService) {}
...
this.resultListService.updateResultList(updatedResultList);

Now in any component where you want the updated resultList, just subscribe to resultList$ from ResultListService:

constructor(..., private resultListService: ResultListService) {}
...
this.resultListService.resultList$
  .subscribe(resultList => console.log('This is the updated resultList: ', resultList));
Sign up to request clarification or add additional context in comments.

1 Comment

really awesome tip. Thank you so much, you helped me alot ! It was very easy to implement!
2

There are other options besides chaining @Input and @Output parameters through multiple components or using a service (which is likely the best solution if you are new to Angular), one of which is making use of shared state.

Using a state management framework such ngrx, ngxs or akita allows you to share both state and changes to that state between components - in this case arrays and changes to their content.

Once set up the store would manage adding the items selected in your child component to the array referenced in the parent component. The two components would not even have to be related to each other.

These two tutorials for ngrx and ngxs both cover a use case similar to yours. The fact that you are using a modal dialog and two lists does not change anything in regards to how the store is used.

This is likely out of scope for what you are trying to accomplish but something you could keep in mind.

Comments

1

If you want to share a value between components, you should do a Service that will be injected in each component where you need it.

@Injectable({
 providedIn: 'root',
})
export class ResultListService {
  public myResultList: string;
}

(With the providedIn: 'root', it will be injected at the root of your app so it will be instancied only one time and the same instance will be shared among components)

Then you pass it in the constructor parameters of your componenents:

export class SidebarComponent   {

  constructor(public resultListService: ResultListService){}

  // this.resultListService.myResultList
}

Comments

0

Component A- HTML

<button (click) = "changeFoo()">Change Value</button>

Component A- Typpescript

    import { SharedService } from './../../shared.service';
constructor(private sharedService: SharedService) {}

Component B-Html

<div style="margin:0; padding:0">
            {{xIsANumberVal == null? '' : "Value Passed From A Component 
            Comp(Parent): "+xIsANumberVal }}
</div>

Component B- Typescript

import { SharedService } from './../../shared.service';
 xIsANumberVal!: number;
constructor(
    private sharedService: SharedService
  ) {}

ngOnInit() {
    this.receiveValueFromService();
  }

    receiveValueFromService() {
        this.sharedService.valueSource.subscribe(value => {
          this.xIsANumberVal = value;
        });
      }

Shared Service

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

@Injectable({
  providedIn: 'root'
})
export class SharedService {

  xIsANumberVal: number = 5;
  valueSource: Subject<number> = new Subject();


  get abc(): Subject<number> {
    return this.valueSource;
  }

  constructor() { }


  changeFoo(xIsANumberVal: number) {
    this.valueSource.next(xIsANumberVal);
  }
}

Working Example: https://stackblitz.com/edit/github-u6xvad?file=src%2Fapp%2Fsecond%2Fsecond.component.ts

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.