一个指令用Angular 2+中的微调器替换加载内容

时间:2017-06-26 11:23:45

标签: angular angular2-directives

在Angular 1中,创建一个用旋转器替换内容的加载指令相当容易,并且使用如下:

<div isLoading="$scope.contentIsLoading"></div>

其中contentHasLoaded是您在数据调用后在控制器中设置的简单布尔值。该指令本身很简单,大部分工作都是在模板中完成的:

<div class="spinner" ng-if="$scope.isLoading"></div>
<div ng-transclude ng-if="!$scope.isLoading"></div>

是否有&#34;清洁&#34;在Angular 2+中做到这一点的方法?通过清理我的意思是1)在Angular中,不使用vanilla JS直接操作DOM和2)可以作为现有元素的单个属性实现吗?

我确实认为这篇文章是后备:Image Loading Directive。但是,它比我想要的更冗长:使用常规组件需要我将所有异步内容包装在新标签中,而不是仅添加属性。

我真正想要的是结构指令中的东西(它应该是为#34;操纵DOM而设计的。&#34;)然而,我所见过的所有例子都是如此是* 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);
    }
  }

}

1 个答案:

答案 0 :(得分:8)

这可以在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。