#Avoid subscription in the component

75 messages · Page 1 of 1 (latest)

velvet coral
#

Hello, for getting out data of the Observable async pipe is favorable, but if I want to make a POST request or a DELETE can I avoid the subscribe from the .ts file or is necessary to subscribe into the component .ts file? Thanks

#
  customActionEvent(event: CustomActionModel) {

    let eventValue = event.value as VehicleTaxDeregistration;

    if (event.id === GridOptions.viewDetails) {

    }
    if (event.id === GridOptions.downloadPdf) {
    /* Download pdf */
this.vehicleTaxDeregistrationService.readApplicationPdf(eventValue.id!).subscribe((result: any) => {
        const a = document.createElement('a');
        const objectUrl = URL.createObjectURL(result);
        a.href = objectUrl;
        a.download = "Cerere";
        a.click();
        URL.revokeObjectURL(objectUrl);
    }
    if (event.id === GridOptions.editApplication) {

    }
  }
#

like here, when I click on a Grid option I want to download an Pdf file

vapid anchor
#

yes its fine to subscribe in the component

#

if you want to be safe make sure you unsubscribe when the component is destroyed

subscription

customActionEvent() {
  this.subscription = something.subscribe()
}

ngOnDestroy() {
  this.subscription?.unsubscribe()
}

Or add some sort of timeout to make sure the observable completes to prevent memory leaks. You only need this if your observable doesn't complete on its own.

naive solstice
#

As a rule of thumb, it's better to always unsubscribe on destruction.

surreal nest
#

Ideally, you would set up your observables in such a way that you dont need that subscribe in the first place. But that's not always easy.

#

That's where I always believed ngrx effects shine.

velvet coral
surreal nest
#

Lets say your data is in an observable called this.data$, you can always get the data from there using all kinds of ways:

const dataFromApi$ = combineLatest([this.data$])
  .pipe(
    switchMap(([data]) => this.someService.doPostWithData(data))
  );

This will automatically trigger the post call when the data changes. Which is not always what u want.
Can add take(1) if u like, or use a specific trigger:

const dataFromApi$ = this.trigger$
  .pipe(
    withLatestFrom([this.data$]),
    switchMap(([data]) => this.someService.doPostWithData(data))
  );

Then call this.trigger$.next() when u want to actually call the API.

#

This will achieve the same, without a single subscription

#

Which is not that different from ngrx effects would work, it's just all abstracted a bit nicely for u.

velvet coral
surreal nest
#

You will always need subscriptions, but you want to avoid manual subscribing.

velvet coral
#

let's say I have a Form, I want to patch all the values for the form

#

and after the user update the dates, I need to do an POST request

surreal nest
surreal nest
velvet coral
#

but initially If I only want to display the data in the template

#

?

#

can I do this?

#

dataFromApi$ | async as dataFromApi ?

surreal nest
#

I dont know what u mean.

#

U need to get the data from the api first.

#

U dont need data for that ?

velvet coral
surreal nest
#

But the first is a GET call?

velvet coral
#

yes

surreal nest
#

So you are talking about something else

#

this is the post call...

#

Does the post call return the same data as the get?

velvet coral
#

in my app yes

#

Usually my flow is to get data from the backend, modify it in a Form and after that submit the new data to the backend

#

how I implemented, I do | async pipe for GET request

#

and after subscribe

#

for the POST Request

surreal nest
#

U can use:

const dataFromApi$ = merge([
  this.someService.getData(),
  this.trigger$
    .pipe(
      withLatestFrom([this.data$]),
      switchMap(([data]) => this.someService.doPostWithData(data))
    )
)];
velvet coral
#

ok so the trigger can contain the form value like a Subject, this.trigger$.next(this.form.getRawValue()) ?

surreal nest
#

it could if u want sure. That would simplfy things:

#
const dataFromApi$ = merge([
  this.someService.getData(),
  this.updateData$
    .pipe(
      switchMap((data) => this.someService.doPostWithData(data))
    )
)];
#

Renamed it to updateData instead.

velvet coral
#

yeah that's look cool, thanks

surreal nest
#

And it also represents what u just said:

#

dataFromApi will represent initial data, as well as data after every update.

velvet coral
#
const dataFromApi$ = merge([
  this.someService.getData(),
  this.updateData$
    .pipe(
      switchMap((data) => this.someService.doPostWithData(data).pipe(tap(() => redirectToSomething()))
    )
)];
#

this will work too?

#

redirect to another page, after the POST request

surreal nest
#

Sure

velvet coral
#

Ok thanks

velvet coral
#

I know combineLatest emit when every observable emit once

#

and forkJoin emit when all observables are completed

surreal nest
#

merge emit from both observables

velvet coral
#

it still work?

surreal nest
#

Yes.

velvet coral
#

hm ok, so that's the difference.

surreal nest
#

What do u mean ?

#

Difference with what ?

velvet coral
#

combineLatest, forkJoin and merge

#

because first two doesn't work if one of observable does not emit or complete

surreal nest
#

Yeah thats true.

velvet coral
#

need to

#

return same type of Data right?

surreal nest
#

Yeah, thats what u want when using merge

velvet coral
surreal nest
#

What ? Different data ?

velvet coral
#

yes

surreal nest
#

Different data shouldnt be represented in a single observable.

velvet coral
#
const viewmodel$ = merge([
  this.someService.getData(),
  this.updateData$
    .pipe(
      switchMap((data) => this.someService.doPostWithData(data).pipe(tap(() => redirectToSomething()))
    )
]).pipe(map(() => map to view model if necessary);
naive solstice