1

In my stackblitz example, I've put a <router-outlet> inside of a ng-template tag so that I can move it between the mobile and desktop parts of the DOM when the window resizes. Eventually something goes wrong and this stops working correctly.

To observe the issue open the link below and resize the internal browser window. You should see the text switch between "Desktop" when window.innerWidth > 600px and "Mobile" otherwise. Keep resizing and eventually something goes wrong.

What can be done to fix this issue?

https://stackblitz.com/edit/angular-oavajy?file=app%2Fapp.component.html

Nate May
  • 3,814
  • 7
  • 33
  • 86

2 Answers2

1

I don't know what issue was there expect the text

something works

was not behaving properly.

i have used ng-container instead of ng-template and it worked properly.

ng-template is used for structural directive like ng-if, ng-for and ng-switch. If you use it without structural directive, nothing happens and renders.

ng-container is used when you don't have a suitable wrapper or parent container.

hope this helps.

Hrishikesh Kale
  • 6,140
  • 4
  • 18
  • 27
  • seems to work in stackblitz, but oddly, not in my local app – Nate May Jun 21 '18 at 06:07
  • this is so strange! are you using any structural directive within it? – Hrishikesh Kale Jun 21 '18 at 06:43
  • `ng-template is used for structural directive like ng-if, ng-for and ng-switch. If you use it without structural directive, nothing happens and renders.` Little wrong, because `ng-template` also used to create view(embedded) – Yerkon Jun 21 '18 at 11:28
  • for more details you can have a look here https://angular.io/guide/structural-directives – Hrishikesh Kale Jun 21 '18 at 11:48
  • 2
    @HrishikeshKale I was following this example, https://netbasal.com/angular-2-understanding-viewcontainerref-acc183f3b682. I think there are use cases beyond structural directives. – Nate May Jun 21 '18 at 13:12
1

First you have omitted break in in switch statement, which is doesn't stop after reaching 'mobile' case. So if you put console.log in each method(loadMobileContent/loadDesktopContent), you will see after switching from mobile to desktop version each method is called:

  switch(newDevice){
      case 'mobile': this.loadMobileContent();
      case 'desktop': this.loadDesktopContent();
    } 

Fix:

 switch (newDevice) {
      case 'mobile':
        this.loadMobileContent();
        break;
      case 'desktop':
        this.loadDesktopContent();
        break;
    }

Also change moveRouterOutlet() method to:

  moveRouterOutlet(fromOutlet: ViewContainerRef, toOutlet: ViewContainerRef): void {
    fromOutlet.clear();
    toOutlet.createEmbeddedView(this.tpl);
  }

StackBlitzh Demo

Here is another solution with declarative approach with using ngIf else feature:

<div>
    <h1 *ngIf="device !== 'mobile' else tpl">Desktop</h1>
    <!-- <div #desktopOutlet></div> -->
</div>

<div>
    <h1 *ngIf="device !== 'desktop' else tpl">Mobile</h1>
    <!-- <div #mobileOutlet></div> -->
</div>

<ng-template #tpl>
    <router-outlet></router-outlet>
</ng-template>

StackBlitz Demo

Hey thanks for the effort. Problem with both solutions is that it will reinitialize the component rendered through the . I need to keep the component state as I switch viewports. that's why I'm trying to detach it, not clear it.

Ok, then you can detach ViewRef from outlet and insert to another:

  moveRouterOutlet(fromOutlet: ViewContainerRef, toOutlet: ViewContainerRef): void {
    let detached = fromOutlet.detach();
    toOutlet.insert(detached);
  }

This will save the component state

Updated StackBlitz

Yerkon
  • 4,548
  • 1
  • 18
  • 30
  • Hey thanks for the effort. Problem with both solutions is that it will reinitialize the component rendered through the ``. I need to keep the component state as I switch viewports. that's why I'm trying to detach it, not clear it. `else` clears it as well. – Nate May Jun 21 '18 at 13:23
  • @NateMay, fixed – Yerkon Jun 22 '18 at 05:09
  • I kiss you my friend! I was trying to figure out what to do with the `viewRef` that `detach()` returns – Nate May Jun 22 '18 at 20:41