在Angular 1中,创建一个用旋转器替换内容的加载指令相当容易,并且使用如下:
<div isLoading="$scope.contentIsLoading"></div>
其中contentHasLoaded是您在数据调用后在控制器中设置的简单布尔值.该指令本身很简单,大部分工作都是在模板中完成的:
<div class="spinner" ng-if="$scope.isLoading"></div> <div ng-transclude ng-if="!$scope.isLoading"></div>
在Angular 2中有一个“干净”的方法吗?通过干净我的意思是1)在Angular中,不使用vanilla JS直接操作DOM和2)可以作为现有元素的单个属性实现吗?
我确实看到这篇文章作为后备:Image Loading Directive.但是,它比我想要的更冗长:使用常规组件需要我将所有异步内容包装在新标签中而不是仅添加属性.
我真正想要的是结构指令中的东西(它应该被设计用于“操纵DOM”.)然而,我见过的所有例子都是像* ngIf这样隐藏内容的东西,但是不插入新内容.具体而言,结构模板1)可以具有模板,或者2)插入组件或3)插入像< div class =“spinner”>< / div>这样简单的东西.到目前为止,这是我最好的尝试:
import { Directive,Input,TemplateRef,ViewContainerRef } from '@angular/core'; @Directive({ selector: '[loading]',inputs: ['loading'] }) export class LoadingDirective { constructor( private templateRef: TemplateRef<any>,private viewContainer: ViewContainerRef ) { } @Input() set loading (isLoading: boolean) { if (isLoading) { this.viewContainer.clear(); // INSERT A COMPONENT,DIV,TEMPLATE,SOMETHING HERE FOR SPINNER } else { this.viewContainer.clear(); // If not loading,insert the original content this.viewContainer.createEmbeddedView(this.templateRef); } } }
解决方法
这可以在你描述的方式在Angular2中完成,你在正确的轨道上.您的结构指令将包含主机元素的模板,您可以注入一个组件来容纳加载图像等.
指示
该指令采用输入参数来指示加载状态.每次设置此输入时,我们都会清除viewcontainer,并根据加载值注入加载组件或主机元素的模板.
@Directive({ selector: '[apploading]' }) export class LoadingDirective { loadingFactory : ComponentFactory<LoadingComponent>; loadingComponent : ComponentRef<LoadingComponent>; @Input() set apploading(loading: boolean) { this.vcRef.clear(); if (loading) { // create and embed an instance of the loading component this.loadingComponent = this.vcRef.createComponent(this.loadingFactory); } else { // embed the contents of the host template this.vcRef.createEmbeddedView(this.templateRef); } } constructor(private templateRef: TemplateRef<any>,private vcRef: ViewContainerRef,private componentFactoryResolver: ComponentFactoryResolver) { // Create resolver for loading component this.loadingFactory = this.componentFactoryResolver.resolveComponentFactory(LoadingComponent); } }
零件
你可以看到除了保存模板之外什么都不做.
@Component({ selector: 'app-loading',template: `<div class="loading"> <img src="assets/loading.svg" alt="loading"> </div>` }) export class LoadingComponent { constructor() { } }
履行
结构指令的用法,绑定到布尔值
<div *apploading="isLoadingBoolean"> <h3>My content</h3> <p>Blah.</p> </div>
注意:您还需要在ngModule的entryComponents数组中包含LoadingComponent.