Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

*ngIf async pipe angular merge with another observable

Please give me some ideas of workaround for my app! I am trying to switch dynamicly template in my component but have odd behavior. Thanks! Here is stackblitz

What I want basically: I want to recieve async data (node) from service in my alert component, and show this data (node) in my #initTemplate, then I want to take id of this data (node), send request with this id and get another data (styles) which I want to display in my #stylesTemplate. Both templates are in my alert component.

What's my problem? I realized desired behavior of my component, but this is not exactly what I need... What I am doing: 1. Click on "pushData" button 2. Look at my alert component 3. Click on change template button (!! component disappears !!) 4. Click on "pushData" again 5. Look at my component with changed template

I need to switch component's template without it's disappearing.

Here is my simplified alert component (see also at stackblitz working sample)

class AlertComponent implements OnInit, OnDestroy {
    private subscription: Subscription;
    message: any;

    node$: Observable<{}>;
    styles$: Observable<{}>;

    constructor(private dataService: DataService) { }

    activeInit: boolean = true;

    ngOnInit() {
        this.node$ = this.dataService.getAsyncData().pipe(share());


        this.styles$ = this.node$.pipe(
            mergeMap(node => {
                if(!!node) {
                  // I need node here, because getSecondAsyncData send request with this data
                    return this.dataService.getSecondAsyncData(node);
                }
                else return of(null);
            }));
    }

    ngOnDestroy() {

    }

    openSecond() {
        this.activeInit = false;
    }

    openFirst() {
      this.activeInit = true;
    }

    close() {
        this.dataService.sendNodeToSubscribe(null);
    }

And here is my html with both templates:

<ng-container *ngTemplateOutlet="activeInit ? initTemplate : stylesTemplate"></ng-container>

<ng-template #initTemplate>
    <div class="card left-settings position-fixed" *ngIf="(node$ | async) as node;">
        <div class="row justify-content-end mx-0">
            <div class="col-0">
                <button type="button" class="btn btn-block btn-ghost-light p-1 px-2" (click)="close()">Close</button>
            </div>
        </div>
        <div class="row custom-width">
            <div class="col-lg-12">
                <button (click)="openSecond()">switch second template</button>

            </div>
        </div>
    </div>
</ng-template>

<ng-template #stylesTemplate>
    <div class="card left-settings position-fixed" *ngIf="(styles$ | async) as styles;">
        <div class="row justify-content-end mx-0">
            <div class="col-0">
                <button type="button" class="btn btn-block btn-ghost-light p-1 px-2" (click)="close()">
          Close
        </button>
            </div>
        </div>
        <div class="row custom-width">
            <label>{{styles.isIcon}}</label>
            <label>{{styles.radius}}</label>
      <button (click)="openFirst()">switch first template</button>
        </div>
    </div>
</ng-template>

Thank you !!

like image 680
Vladrimir Eryign Avatar asked Aug 27 '18 11:08

Vladrimir Eryign


People also ask

How do you use async pipe in NgIf?

The async pipe allows us to subscribe to an Observable or Promise from the template and returns the value emitted. The async pipes subscribe to the observable when the component loads. It unsubscribes when the component gets destroyed.

What is Asyncpipe?

The async pipe subscribes to an Observable or Promise and returns the latest value it has emitted. When a new value is emitted, the async pipe marks the component to be checked for changes. When the component gets destroyed, the async pipe unsubscribes automatically to avoid potential memory leaks.

Why async pipe is impure?

Because of the way Promise s work, Angular's async pipe has to be impure (meaning that it can return different outputs without any change in input). The transform method on Pipe s is synchronous, so when an async pipe gets a Promise , the pipe adds a callback to the Promise and returns null.

Is angular Observable async?

Angular makes use of observables as an interface to handle a variety of common asynchronous operations. For example: The HTTP module uses observables to handle AJAX requests and responses. The Router and Forms modules use observables to listen for and respond to user-input events.


1 Answers

You just have to replace below code,

use BehaviorSubject : A BehaviorSubject holds one value. When it is subscribed it emits the value immediately. A Subject doesn't hold a value.

private subject = new Subject<any>();

with

private subject = new BehaviorSubject(new String());

here's is updated Stackblitz

Updated!!

Thank you!! Nice advice, that's work fine, but I need my component to be hidden before recieved real data. To do that, I modified your solution, now I use this:

private subject = new BehaviorSubject(null);
like image 90
Aniket Avhad Avatar answered Oct 13 '22 00:10

Aniket Avhad