在Angular2中将服务作为输入传递

时间:2016-07-14 16:38:59

标签: angular

我想创建一个通用列表组件,其中包含我希望我的所有列表都具有的几个功能。理想情况下,我想使用不同的服务作为组件的输入来呈现不同的数据集。角度2有可能吗?

修改角度2文档中的示例

@Component({
    selector: 'Generic List',
    template: 
    `
    <h2>Items</h2>
    <ul class="items">
      <li *ngFor="let item of items"
          [class.selected]="isSelected(item)"
          (click)="onSelect(item)">
        <span class="badge">{{item.id}}</span> {{item.name}}
      </li>
    </ul>
    `
})
export class GTComponent {
    @Input() someService: Service;

     items: Item[];
     private selectedId: number;

    isSelected(item: Item) { return item.id === this.selectedId; }

    onSelect(item: Item) {
    }
}

如果可以,如果服务具有一个返回promise的名为getItems()的函数,我将如何使用服务中的数据填充items数组。

1 个答案:

答案 0 :(得分:2)

我也有同样的需求,最后我设法实现了该实现,到目前为止看来效果很好。 该实现是用 Angular 8 编写的。

1。定义服务

所有将作为@Input传递到子组件的服务都应有一个名为getItems()的方法,因此,首先,我创建了一个抽象类,该抽象类仅包含以下内容的定义:方法。此类实际上只是一个向Angular通知getItems()方法的容器:

@Injectable()
export abstract class ItemsService {

  constructor() { }

  /**
   * Returns a list of all items
   */
  abstract getItems(): Observable<Item[]>;

} 

然后,我们可以创建将实现ItemsAService的服务(ItemsBServiceItemsCServiceItemsService),如下所示:

import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { ItemsService } from './items.service';
import { Item } from './item';

const ITEMS_A: Item[] = [
  // our items collection
];


@Injectable()
export class ItemsAService implements ItemsService {

  constructor() { }

  getItems(): Observable<Item[]> {
    return of(ITEMS_A);
    // of(ITEMS_A) returns an Observable<Item[]> that emits the array of mock items.
    // in real life, you'll call HttpClient.get<Item[]>() which also returns an Observable<Item[]>:
   // return this.httpClient.get<Item[]>
  }

}

... ItemsBServiceItemsCService的相同代码。

有关为Angular Services here创建界面的更多信息。

2。父组件

我们的通用列表组件将包含在父组件中。在此父组件中,我们将注入上述服务,如下所示:

import { Component } from '@angular/core';
import { ItemsAService } from './items-a.service';
import { ItemsBService } from './items-b.service';
import { ItemsCService } from './items-c.service';

@Component({
  ...
})

export class AppComponent  {
 
 constructor(
   public itemsAService: ItemsAService,
   public itemsBService: ItemsBService,
   public itemsCService: ItemsCService
 )  { }

}

然后,在模板中,我们有:

<app-generic-list
  name="A"
  [service]="itemsAService"
>
</app-generic-list>

<app-generic-list
  name="B"
  [service]="itemsBService"
>
</app-generic-list>

<app-generic-list
  name="C"
  [service]="itemsCService"
>
</app-generic-list>

3。通用列表组件

我们将在此组件中拥有一个@Input() service,键入ItemsService,然后从服务中的getItems()钩子中调用ngOnInit()方法:

import { Component, OnInit, Input, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { ItemsService } from '../items.service';
import { Item } from '../item';

@Component({
  selector: 'app-generic-list',
  ...
})

export class GenericListComponent implements OnInit, OnDestroy {
   @Input() name: string;
   @Input() service: ItemsService;

  items: Item[];
  subscription: Subscription;


  constructor() { }

  ngOnInit() {
    if (!this.service) return;
    this.subscription = this.service.getItems()
      .subscribe(items => this.items = items);
  }

  // other methods here

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

请注意,父组件和子组件(通用列表)将共享服务的同一实例。


完整示例

https://stackblitz.com/edit/angular-mgubup


我很想知道是否还有另一种更可取的方法来实现这一目标。