【发布时间】:2016-03-03 14:58:29
【问题描述】:
如何在“编写代码的角度方式”中的angular2中正确连接两个指令,或一个指令到一个组件(这也是一个指令)?
由于有关 angular2 的文档仍然非常稀缺,因此非常感谢任何见解或参考。
这是每个 angular2 示例显示的内容 - 通过 ngModel 绑定到 string:
@Component({
template: 'Hello <input type="text" [(ngModel)]="myVariable">!'
})
class ExampleComponent() {
myVariable: string = 'World';
}
假设我想在 自定义组件 上使用 ngModel,它不代表 strings,而是任何其他值,例如 number 或类或接口:
interface Customer {
name: string;
company: string;
phoneNumbers: string[];
addresses: Address[];
}
@Component({
selector: 'customer-editor',
template: `
<p>Customer editor for {{customer.name}}</p>
<div><input [(ngModel)]="customer.name"></div>`
})
class CustomerEditor {
customer: Customer;
}
为什么我使用ngModel,你可能会问,什么时候任何其他属性会使数据绑定更容易?好吧,我正在为 angular2 实现一个设计 shim,这些组件将像(或与)原生 <input>s 一样使用:
<input name="name" [(ngModel)]="user.name">
<pretty-select name="country" [(ngModel)]="user.country" selectBy="countryCode">
<option value="us">United States of America</option>
<option value="uk">United Kingdom</option>
...
</pretty-select>
user.country 将是一个 object,而不是 string:
interface Country {
countryCode: string,
countryName: string
}
class User {
name: string;
country: Country;
...
}
到目前为止我所做的工作,但“感觉不对”:
GitHub repository for this example
要将提供给ngModel 指令的引用与我的CustomerEditor 组件链接起来,目前我正在使用我自己的ControlValueAccessor:(简化)
const CUSTOMER_VALUE_ACCESSOR: Provider = CONST_EXPR(
new Provider(NG_VALUE_ACCESSOR, {
useExisting: forwardRef(() => CustomerValueAccessor)
})
);
@Directive({
selector: 'customer-editor[ngModel]',
providers: [CUSTOMER_VALUE_ACCESSOR]
})
@Injectable()
class CustomerValueAccessor implements ControlValueAccessor {
private host: CustomerEditor;
constructor(element: ElementRef, viewManager: AppViewManager) {
let hostComponent: any = viewManager.getComponent(element);
if (hostComponent instanceof CustomerEditor) {
this.host = hostComponent;
}
}
writeValue(value: any): void {
if (this.host) { this.host.setCustomer(value); }
}
}
现在,ControlValueAccessor 让我感到不安的是我获取主机组件引用的方式:
if (hostComponent instanceof CustomerEditor) {
this.host = hostComponent;
}
这不仅需要 3 个应该足够的依赖项(ElementRef、AppViewManager、CustomerEditor),而且在运行时进行类型检查也感觉非常错误。
在 angular2 中获取对主机组件的引用的“正确”方式是什么?
我尝试过的其他事情,但还没有开始工作:
-
This answer by Thierry Templier 在 ControlValueAccessor 的构造函数中注明组件类,以便通过 angular 进行注入:
class CustomerValueAccessor implements ControlValueAccessor { constructor(private host: CustomerEditor) { } }不幸的是,这对我不起作用,并给了我一个例外:
无法解析“CustomerValueAccessor”的所有参数(未定义)。确保所有参数都使用 Inject 进行修饰或具有有效的类型注释,并且 'CustomerValueAccessor' 使用 Injectable 进行修饰。
-
使用
@Host:class CustomerValueAccessor implements ControlValueAccessor { constructor(@Host() private editor: CustomerEditor) { } }抛出与上述解决方案相同的异常。
-
使用
@Optional:class CustomerValueAccessor implements ControlValueAccessor { constructor(@Optional() private editor: CustomerEditor) { } }不抛出异常,但
CustomerEditor未被注入并保持null。
由于角度变化/变化非常频繁,the specific versions I am working with might be relevant, which is angular2@2.0.0-beta.6。
【问题讨论】:
-
我猜如果
CustomValueAccessor应该是一个通用的,那么它应该避免访问主机元素。你为什么需要这个?如果绑定到组件,那么组件本身就可以实现ControlValueAccessor接口,那么访问宿主应该没有问题。 -
如果你以这种方式使用它,你可能需要将访问器类添加到
directives。
标签: typescript angular angular-ngmodel