【问题标题】:Multiple occurrences of the same custom directive Angular2多次出现相同的自定义指令 Angular2
【发布时间】:2018-01-27 07:36:12
【问题描述】:

我目前正在构建一个 Angular 应用程序,我试图在指令(作为组件)的帮助下使代码高度可重用。

<div class="container container-fluid" >
  <div class="row">
    <table class="table table-responsive table-hover">
      <thead class="thead-inverse">
      <tr>
        <th *ngFor="let column of columns">{{column.header}}</th>
      </tr>
      </thead>
      <tbody>
      <tr *ngFor="let row of rows;trackBy: trackByID;">
        <td *ngFor="let column of columns">{{row[column.field]}}
        </td>
      </tr>
      </tbody>
    </table>
  </div>
  <xfd-progressbar></xfd-progressbar>
  <div class="row col-lg-offset-5">
    <ngbd-pagination-basic></ngbd-pagination-basic>
  </div>
</div>

以上是我创建的具有可重用表的指令。我的一般要求是每页有一个表格。

这是相同的相应组件 -

import {Column} from "../models/Column";
import {Component, OnInit} from "@angular/core";
import {PaginationService} from "../services/PaginationService";
import {GridLoadUtil} from "../util/GridLoadUtil";
import {ProgressBarService} from "../services/ProgressBarService";

/**
 * Created by ppandey on 6/12/2017.
 */

@Component({
    selector: 'xfd-table',
    templateUrl: './table.component.html',
    styleUrls: ['./table.component.css']
})
export class TableComponent implements OnInit{
  columns: Column[]= [];
  rows: any[] = [];

  constructor(private paginService: PaginationService,
            private tableLoader: GridLoadUtil,
            private progressBarService: ProgressBarService) {
    this.paginService.itemsToDisplayChange.subscribe((value) => {
      this.rows = value
    });

    this.tableLoader.columnsChange.subscribe((values) => {
      this.columns = values;
    });
  }

  ngOnInit() {
    this.tableLoader.beforeDataLoaded();
    this.progressBarService.startProgress();
  }
}

如您所见,我的组件使用 Services(GridLoadUtil) 为其提供数据,这使得代码高度解耦。

这就是我进入泡菜的地方。如果我想在一个页面上有多个表,具有不同的数据和结构,它不能作为每个组件所绑定的服务是 Singleton。

我可以选择不注入服务,并将每个服务作为 setter 提供,但在这种情况下,我需要为每个服务创建子类,目前我不需要这样做。另外,我的代码会耦合。

你们认为我可以采取什么方向来解决这个问题?

谢谢, 普拉提克

【问题讨论】:

    标签: javascript angular angular2-services angular2-directives


    【解决方案1】:

    您可以创建一个指令来在那里提供服务。 Angulars DI 在查找 TableLoader 服务时会找到该提供者,因为它最接近组件(如果组件本身不提供):

    @Directive({
      selector: [tableLoader1],
      providers: [{provide: GridLoadUtil, useClass: GridLoadUtil1}],
    })
    class TableLoader1Directive {}
    
    @Directive({
      selector: [tableLoader2],
      providers: [{provide: GridLoadUtil, useClass: GridLoadUtil2}],
    })
    class TableLoader2Directive {}
    

    那么你就可以像这样使用它了

    <xfg-table tableLoader1></xfg-table>
    <xfg-table tableLoader2></xfg-table>
    

    【讨论】:

    • 谢谢@Gunter。为了确保我做对了,该指令将仅用于区分我想为组件提供的服务。此外,示例中提供的两个指令具有相同的类名,错字?还是有效的?
    • 是的,该指令只是为了提供服务。根据您的用例,您还可以将值传递给指令中的输入,并通过将服务注入指令本身并将值传递给服务来使用该值配置您的服务。如果这适用于您的用例,则不需要多个指令(但您也可以混合使用这些方法)。抱歉,重复名称是复制粘贴错误。
    • 它看起来确实可行。明天会试一试,并将您的答案投票为正确。现在已经投票了:)谢谢!
    • 你不能根据输入来修改提供者,但是你可以将一个提供者从指令中注入到指令的构造函数中,然后在ngOnInit()中你可以做this.tableLoader.setConfig(this.someInput);。组件和指令注入相同的服务实例,因此当您从指令修改状态时,它也会影响组件。在调用指令的ngOnInit 之前,您需要确保组件不会对服务造成操作,但如果您使用 Observables(或 BehaviorSubject),这应该不是问题。
    • 没问题!将您的答案标记为正确,因为它看起来像是正确的答案。如果我卡住了,可能会问你一个问题:)
    猜你喜欢
    • 1970-01-01
    • 2016-07-16
    • 1970-01-01
    • 2019-03-14
    • 2023-04-01
    • 1970-01-01
    • 2017-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多