(Маршрутизируемый компонент) Дерево данных со смежной панелью сведений

Мы создаем приложение Angular 2 с навигационным деревом (слева) и смежной панелью подробностей (справа).

Я хочу визуализировать около 20-30 различных компонентов в одной области детализации, в зависимости от того, какой узел дерева выбран.

Чтобы отправить много компонентов к одному RouterOutlet кажется, мне нужно загрузить все эти компоненты в один родительский компонент, где определен выход; Я бы предпочел не иметь такой монолитный компонент верхнего уровня.

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

В дереве может быть выбран только один узел за раз. Когда узел выбран, все остальные не родительские узлы закрываются, и список дочерних узлов для выбранного узла загружается по сети и отображается под выбранным узлом. Подробная информация, относящаяся к выбранному узлу, также загружается по сети и отображается в общей области правой панели, заменяя любую другую информацию, которая ранее отображалась там.

Разные узлы представляют разные функции приложения и содержат разные типы сущностей. Следовательно, различные узлы дерева требуют:

  • различные дочерние шаблоны / компоненты для расширения дочернего дерева (некоторые узлы дерева перечисляют имена контактов, другие содержат встречи и т. д.)
  • различные шаблоны / компоненты загружаются в области сведений

Вот пример:

  • назначения
    • Джо 11 утра
    • Сью 12:00
  • люди
    • Джо Смит
    • Сью Ли (выбрано)
      • 3 дня назад
      • 5 дней назад

Детальная панель будет отображать информацию о Сью Ли.

В настоящее время мы используем наши основные маршруты для управления деревом. Мы называем CanActivate ждать разрешения данных дочернего узла, прежде чем рендерить его маршрутизируемый компонент. Затем мы манипулируем DOM, чтобы привить узел на дереве сразу после его рендеринга. Дерево работает само по себе. Мне нравится, что навигация по основному URL-адресу приложения управляется, как и следовало ожидать от дерева маршрутов; хотя я бы приветствовал альтернативные предложения.

Мы пытаемся использовать Aux Routes для отображения правильного шаблона панели подробностей. Соответствующие узлы дерева понимают, как "инициировать" правильную область сведений, используя простой маршрут Aux. Однако у нас есть две проблемы:

  1. Aux Routes не поддерживают CanActivate так что пока @Resolve Декоратор доступен в Angular 2, мы не можем легко отложить рендеринг для Aux Components до разрешения данных. Это проблема с низким приоритетом, так как она будет исправлена ​​в выпуске Angular.

  2. Все подробные вспомогательные компоненты должны быть загружены в один родительский компонент, чтобы каждый из них мог перезаписывать один и тот же родительский вспомогательный компонент. RouterOutlet, Есть ли другой способ сделать это, который не требует такого массивного компонента верхнего уровня?

1 ответ

Это похоже на тот же подход, который используется в динамических вкладках Angular 2 с выбранными пользователем компонентами, которые также могут помочь.

Используя элемент обертки вокруг ViewContainerRef.createComponent() (бывший DynamicComponentLoader.loadXxx() Вы можете добавить один основной компонент маршрутизатором, который отображает список компонентов в зависимости от данных, которые он передает (например, из общего сервиса)

@Component({
  selector: 'dcl-wrapper',
  template: `<div #target></div>`
})
export class DclWrapper {
  @ViewChild('target', {read: ViewContainerRef}) target;
  @Input() type;
  cmpRef:ComponentRef;
  private isViewInitialized:boolean = false;

  constructor(private resolver: ComponentResolver) {}

  updateComponent() {
    if(!this.isViewInitialized) {
      return;
    }
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }
   this.resolver.resolveComponent(this.type).then((factory:ComponentFactory<any>) => {
      this.cmpRef = this.target.createComponent(factory)
    });
  }

  ngOnChanges() {
    this.updateComponent();
  }

  ngAfterViewInit() {
    this.isViewInitialized = true;
    this.updateComponent();  
  }

  ngOnDestroy() {
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }    
  }
}

построить список дочерних компонентов, таких как

@Component({
  selector: 'inserted-by-router',
  directives: [DclWrapper],
  template: `<dcl-wrapper *ngFor="let type in sharedService.types" [type]="type"></dcl-wrapper>`})
export class InsertedByRouter {
  constructor(private sharedService.types) {}
}
Другие вопросы по тегам