具有嵌入式else模板的自定义ngIf指令

时间:2019-05-12 08:35:23

标签: angular typescript

这是Angular应用程序中的常见模式,它使用ngIf指令显示来自Observable的某些数据,并提供else模板以在数据加载时显示占位符。

<data-view *ngIf="data$ | async as data; else progress" [items]="data">
</data-view>

<ng-template #progress>
  <mat-icon></mat-icon>
  <mat-progress></mat-progress>
</ng-template>

但是,它需要多次重复else模板,异步管道和 as 子句。是否可以避免这样的样板代码以及如下的自定义指令:

<data-view *ngWait="data$" items="data">
</data-view>

我了解如何将ngIf与异步管道结合使用,但是我不知道如何将else模板嵌入到自定义指令中。

2 个答案:

答案 0 :(得分:1)

您可以在结构指令中使用createComponent中的ViewContainerRef

@Directive({
  selector: "{Your-Selector}"
})
export class StructuralDirective implements OnInit {
  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef,
    private resolver: ComponentFactoryResolver
  ) {}

  @Input() {Your-Selector}: boolean;

  ngOnInit() {
    if (this.{Your-Selector}) {
      this.viewContainer.createEmbeddedView(this.templateRef);
    } else {
      let factory = this.resolver.resolveComponentFactory({Your component that holds default message});
      this.viewContainer.createComponent(factory);
    }
  }
}

还必须在条目组件内添加{Your component that holds default message}

这里是CodeSandbox的一个简单演示,您可以将其用作参考。

答案 1 :(得分:0)

我假设数据视图不是您的自定义组件,否则将#progress模板放入数据视图模板中并进行处理,重复代码更少,会更容易。在您的情况下,可以通过指令动态地进行内容投影来实现所需的目标。这些答案可能有助于该方向: