简体   繁体   中英

*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 !!

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM