1

I have a scenario, my child component takes BehaviourSubject as Input and that(child) subscribes it internally. I need to filter/map on BehaviourSubject in the parent, so that when somewhere next() is called then child subscription receives map/filtered values.

export class ParentComponent {
    public myBSubject: BehaviorSubject<ListFilter[]> = new BehaviorSubject<ListFilter[]>(undefined);
    public ngOnInit(): void {
        this.myBSubject = this.myBSubject.pipe(
          map((filters): ListFilter[] => {
            // Do some manipulation with filters
          return filters;
        }));
    }
}

tempalate

<child [myBSubject]="myBSubject"> </child>

ChildComponent (I have no control on it.)

export class ChildComponent {
 @Input()
  public myBSubject: BehaviorSubject<ListFilter[]> = new BehaviorSubject<ListFilter[]>(undefined);
  
  // somewhere subscription of myBSubject

}

the problem is the .pipe(map) converting BehaviourSubject to Observable, which is not assignable. and without assigning map callback not called because immutable map.

by making .pipe(map..) as BehaviourSubject<ListFilter> working fine but i'm feeling its not a good solution. Please help me to achieve this in a better way, Thank you.

harpal
  • 426
  • 4
  • 12
  • So this behaviorsubject is created in parent and only lives there? (Besides the child) DId I understand correctly? – AT82 Dec 02 '21 at 13:36
  • Its reference remains in parent and child both. The only thing is child initilizes with default if not sent from parent. – harpal Dec 02 '21 at 13:44
  • 1
    I know you can't change the ChildComponent, but if there is any way to talk to the team that manages that component, I'd suggest changing to something like this: https://twitter.com/joeflateau/status/1466479422207365137 – DeborahK Dec 02 '21 at 19:10
  • I saw in comment that you are using a library, what library is used in the child? Who knows, maybe this could be an XY problem as well. So please provide a [mcve] – AT82 Dec 03 '21 at 07:50
  • here I tried to add an example, maybe this provide more context. – harpal Dec 03 '21 at 08:37

1 Answers1

1

Please have a look at this answer to a similar question.

Besides the 2 options described there (using an input property setter or implementing OnChanges), I believe there is a third one which might suit your needs, given that the data for your BehaviorSubject comes from another observable.

In your parent component, update the value of the BehaviorSubject in the subscription body of this first observable. Then in the template of the parent component, pass the BehaviorSubject through the async pipe and use that as input for the child component.

Parent component:

export class ParentComponent {
    public myBSubject: BehaviorSubject<ListFilter[]> = new BehaviorSubject<ListFilter[]>(undefined);
    public ngOnInit(): void {
        this.firstObservable.pipe(
          map(value => // map to ListFilter array here)
        ).subscribe(result => this.myBSubject.next(result));
    }
}

Template:

<child [myBSubject]="myBSubject | async"> </child>
Karel
  • 79
  • 1
  • 5
  • No that's not in my case, as I mentioned in the question it is hard to change in the child component, it's written by some else(lib). And there is no other observable, I want the when myBSubject(behaviourSubject) emit values then subscriber of it would get mapped result. – harpal Dec 02 '21 at 15:14
  • And can't you map the values within the `.next()` function of the BehaviorSubject? – Karel Dec 02 '21 at 16:37
  • yes in the parent component I can map, but not that were emitted from the child component. – harpal Dec 03 '21 at 05:01
  • I don't really understand your previous reply, but looking at your example (and depending on where you get the data) you might be able to do `myBSubject.next(someArray.map(values => //mapping function here))` instead of piping – Karel Dec 03 '21 at 05:55