将组件作为“参数”传递给Angular 2中的另一个组件

时间:2016-01-03 11:17:52

标签: typescript angular

我是网络开发的新手,我刚刚开始构建一个Angular 2应用程序。此时我正在尝试创建一些CRUD组件/表单,但我发现自己复制了很多代码。在设计使用Angular2的CRUD应用程序时,我不会问为什么是避免代码重复和实现组件可重用性的常见最佳实践,因为帖子将被锁定。我宁愿专注于一个特定的方面:

我有一个“CRUD页面”,它有一个列表(实际上是一个html表)的资源和几个打开“创建”,“读取”和“编辑”表单的按钮。该列表本身是一个单独的组件,创建/读取/编辑单独的组件也是如此。表的每一行包括另一个知道如何呈现资源项的组件。我将调用此<resource-item>组件。但是,我有几个“CRUD页面”,每个页面用于不同的资源。所以我想要的是为所有资源重用列表组件。因此,首先要做的是将输入或属性添加到列表组件以控制其标签。到现在为止还挺好。

但是<resource-item>组件怎么样?我的应用程序的每个资源可能具有完全不同的结构。因此,我将需要不同资源的不同组件,例如:<resource-a-item><resource-b-item>等。如何在每次创建列表组件时指定要使用的资源项组件?

感谢您的时间。

3 个答案:

答案 0 :(得分:11)

这似乎非常适合内容翻译。

Angular 2附带一个名为 ng-content 的组件,允许您插入外部html /组件作为组件的内容。

您只需在要在组件中显示内容的位置使用

例如:

import {Component} from 'angular2/core'

@Component({
  selector: 'holder',
  providers: [],
  template: `
    <div>
      <h2> Here's the content I got </h2>
      <ng-content></ng-content>
    </div>
  `,
  directives: []
})
export class Holder {
  constructor() {

  }
}

您可以通过以下方式指定要从组件父级注入的内容:

import {Component} from 'angular2/core';
import {Holder} from './holder';

@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <div>
      <h2>Hello {{name}}</h2>
      <holder>
        <div>yeey transcluded content {{name}}</div>
      </holder>
    </div>
  `,
  directives: [Holder]
})
export class App {
  constructor() {
    this.name = 'Angular2'
  }
}

您可以看到工作示例here

在您的情况下,您可以使列表行/项目成为可以接受某些内容以显示的组件。

答案 1 :(得分:2)

我正在研究可能对您有用的可重用组件方案。在此示例中,它是configurator组件,它具有基本结构,并且用于通过values对象配置其他组件(来自form.values)。

import {Component, Input, EventEmitter, ViewEncapsulation} from 'angular2/core';

@Component({
  encapsulation: ViewEncapsulation.None,
  selector: 'configurator',
  template: `
    <div [hidden]="!active">
      <span (click)="active = false">&times;</span>
      <h3>{{ title }}</h3>
      <form>
        <ng-content></ng-content>
      </form>
    </div>
  `
})
export class ConfiguratorComponent {
  @Input() title: string;
  @Input() values: any = {};
  @Input() emitter: EventEmitter<any>;

  public active: boolean = false;

  set(key: string, value?: any) {
    this.values[key] = value || !this.values[key];
    if (this.emitter)
      this.emitter.emit(this.values);
  }
}

我在主机组件中使用它作为它配置的组件的兄弟。

@Component({
  directives: [
    ConfiguratorComponent,
    ResourceOneComponent,
  ],
  pipes: [...],
  providers: [...],
  template: `
  <configurator title="Resource One" #cfg [values]="one.values" [emitter]="configEmitter">

    <label>Size:
      <input type="number" min="0" #size [value]="cfg.values.size" (change)="cfg.set('size', size.value)">
    </label>

  </configurator>
  <resource-one #one [emitter]="configEmitter"></resource-one>
  `
})
class HostComponent {
  public configEmitter = EmitterService.get('resource_one');
}

资源组件可以是:

class ResourceOneComponent extends CRUDComponent {
  public values: { size: 5 };
  private ngOnChanges() {
    if (this.emitter) 
      this.emitter.subscribe(values => {
        // use values from configurator
      });
  }
}

这是我用来在兄弟组件之间进行通信的服务:

import {Injectable, EventEmitter} from 'angular2/core';

@Injectable()
export class EmitterService {
  private static _emitters: { [ID: string]: EventEmitter<any> } = {};
  static get(channel: string): EventEmitter<any> {
    if (!this._emitters[channel]) 
      this._emitters[channel] = new EventEmitter();
    return this._emitters[channel];
  }
}

编辑:对于您的用例,这可能是“过度杀戮”(:我刚看到其他答案,两者都适用于更简单的场景......我希望尽可能地将事物分开,所以每个组件都做了一件事。我一直在研究可重用组件之间的通信方式,这个解决方案可以很好地工作。认为分享可能很有用(;

答案 2 :(得分:1)

如果修复了不同resource-x-item>的列表,则可以使用ngSwitch(ng-switch in Angular2)。 您还可以使用路由动态添加组件。 如果以上内容不适用于您的用例,您可以使用DynamicComponentLoader`(How to use angular2 DynamicComponentLoader in ES6?