Перемещение <ng-template> между 2 ViewContainerRefs иногда не удается

В моем примере Stabblitz я поставил <router-outlet> внутри ng-template пометить, чтобы я мог перемещать его между мобильной и настольной частями DOM при изменении размера окна. В конце концов, что-то идет не так, и это перестает работать правильно.

Чтобы увидеть проблему, откройте ссылку ниже и измените размер окна внутреннего браузера. Вы должны увидеть текстовый переключатель между "Рабочим столом", когда window.innerWidth > 600px и "Мобильный" в противном случае. Продолжайте изменять размер, и в конце концов что-то пойдет не так.

Что можно сделать, чтобы исправить эту проблему?

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

2 ответа

Решение

Сначала вы пропустили break in в операторе switch, который не останавливается после достижения "мобильного" случая. Поэтому, если вы поместите console.log в каждый метод (loadMobileContent/loadDesktopContent), вы увидите, что после переключения с мобильной версии на настольную версию каждый метод вызывается:

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

Fix:

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

Также изменить moveRouterOutlet() метод для:

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

StackBlitzh Демо

Вот еще одно решение с декларативным подходом с использованием функции ngIf else:

<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

Эй, спасибо за усилия. Проблема обоих решений заключается в том, что он будет повторно инициализировать компонент, отображаемый через. Мне нужно сохранить состояние компонента, когда я переключаю видовые окна. вот почему я пытаюсь отделить это, а не очистить это.

Хорошо, тогда вы можете отсоединить ViewRef из розетки и вставьте в другую:

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

Это сохранит состояние компонента

Обновлен StackBlitz

Я не знаю, какая проблема была там, ожидайте текст

что-то работает

не вел себя должным образом.

я использовал ng-container вместо ng-template и это сработало правильно.

Шаблон ng используется для структурных директив, таких как ng-if, ng-for и ng-switch. Если вы используете его без структурной директивы, ничего не происходит и не рендерится.

ng-container используется, когда у вас нет подходящей оболочки или родительского контейнера.

надеюсь это поможет.

Другие вопросы по тегам