0

I have Observable that contains big object inside. I want to pass only one property to child component as observable. I can you pipe in component, but I need to create one more observable for it. Can I make it inside html?

// this is service;
this.theObject$ = new BehaviourSubject<TheObject>(null);
this.theObject = {...alot, 
    title as string,
    neededValue as number
};
this.theObject$.next(theObject);

get getTheObject (): Observable<TheObject> {
   return this.theObject as Observable;
}

// component:
theObject: Observable<TheObject>;
ngOnInit(){
this.theObject = this.service.getTheObject;
}

// component html:
<div>
<span>{{(theObject | async).title}}</span>
<app-custom-component [neededValue$]="(theObject | async)?.neededValue"></app-custom-component>
</div>

//Custom Component
some: number;
@Input()'neededValue': Observable<number>;
ngOnInit(){
  this.neededValue.subscribe(res => {
    this.some = res;
  })
}

I got an error here:

ERROR TypeError: Cannot read property 'subscribe' of undefined

I think problem is here: (theObject | async)?.neededValue. Is there a way to solve this without extra observables? Also I dont don't to pass to custom component all the big object.

2
  • The variable name is inconsistent between template and controller (neededValue$ vs neededValue). Commented Jun 11, 2021 at 12:51
  • I dont don't to pass to custom component all the big object - You can use pipe/map to extract a property => public neededValue$ = this.service.getTheObject().pipe(map(o => o.neededValue)); Then use it in your template like [neededValue]="neededValue$ | async" Commented Jun 11, 2021 at 12:53

1 Answer 1

2

If you only want to pass BehaviorSubject Value, why not use asObservable() method

  theObject             = new BehaviorSubject<TheObject>(null);

  // This obs will contain the entire object
  theObject$            = this.theObject.asObservable();

  // This obs will contain only neededValue
  theObjectNeededValue$ = this.theObject.asObservable().pipe(pluck('neededValue'));

Inside the component simply assign the service observable variables and use them with async pipe or if you want to pass them to child component as observable.

// component.ts
theObject$ = this.service.theObject$;
theObjectNeededValue$ = this.service.theObjectNeededValue$;

// component html:
<div>
<span>{{(theObject$ | async).title}}</span>
<app-custom-component [neededValue$]="theObjectNeededValue$"></app-custom-component>
</div>
Sign up to request clarification or add additional context in comments.

2 Comments

I just want to make my code more ellegant and not to subscribe to 2 observables
Well, with extra observable whose underlying datasource is still value of BehaviorObject, you would be able to manage the application in better way. Not sure about use case here, but if you only want to display custom component based on truthy value of neededValue, doing it with only one observable will make it more messy.

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.