【问题标题】:A directive replacing loading content with spinner in Angular 2+在 Angular 2+ 中用微调器替换加载内容的指令
【发布时间】:2017-11-29 05:27:48
【问题描述】:

在 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) 插入像 &lt;div class="spinner"&gt;&lt;/div&gt; 这样简单的东西。到目前为止,这是我最好的尝试:

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);
    }
  }

}

【问题讨论】:

  • 嗨,如果你愿意,我最近在一个项目中工作,我使用指令创建一些内容并应用一些类......它可能会对你有所帮助:github.com/damnko/angular2-django-movies/blob/master/…
  • 您希望如何应用该指令?显示一些 html
  • 好吧,我确实指定了一个属性,并且我确实给出了我从 Angular 中知道的示例。如果我知道在 Angular 2 中这样的事情是如何完成的,我就不会问这个问题,但我想它会像
    Normal content goes here
    跨度>

标签: angular angular2-directives


【解决方案1】:

这可以按照您描述的方式在 Angular2+ 中完成,您走在正确的轨道上。您的结构指令将容纳宿主元素的模板,您可以注入一个组件来容纳加载图像等。

指令 该指令采用输入参数来指示加载状态。每次设置此输入时,我们都会清除视图容器并根据加载值注入加载组件或宿主元素的模板。

@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。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-13
    • 1970-01-01
    • 2019-10-21
    相关资源
    最近更新 更多