我想为已经部署在Angular 2中的一些组件创建扩展,而不必几乎完全重写它们,因为基本组件可能会发生更改,并希望这些更改也反映在其派生组件中.
我创建了这个简单的例子,试图更好地解释我的问题:
使用以下基本组件app/base-panel.component.ts:
import {Component, Input} from 'angular2/core';
@Component({
selector: 'base-panel',
template: '<div class="panel" [style.background-color]="color" (click)="onClick($event)">{{content}}</div>',
styles: [`
.panel{
padding: 50px;
}
`]
})
export class BasePanelComponent {
@Input() content: string;
color: string = "red";
onClick(event){
console.log("Click color: " + this.color);
}
}
Run Code Online (Sandbox Code Playgroud)
您是否只想更改另一个衍生组件,例如,在示例颜色的情况下,基本组件行为app/my-panel.component.ts:
import {Component} from 'angular2/core';
import {BasePanelComponent} from './base-panel.component'
@Component({
selector: 'my-panel',
template: '<div class="panel" [style.background-color]="color" (click)="onClick($event)">{{content}}</div>',
styles: [`
.panel{
padding: 50px;
}
`]
})
export class MyPanelComponent extends BasePanelComponent{
constructor() { …Run Code Online (Sandbox Code Playgroud) 假设我们想在angular2中使用某个库中的组件(例如来自material2).组件注释如下所示:
@Component({
moduleId: module.id,
selector: 'md-input',
templateUrl: 'input.html',
styleUrls: ['input.css'],
providers: [MD_INPUT_CONTROL_VALUE_ACCESSOR],
host: {'(click)' : 'focus()'}
})
Run Code Online (Sandbox Code Playgroud)
该组件附带"默认"样式表,即"input.css".如果我们在应用程序中使用此组件,我们可能希望覆盖/扩展某些样式,而无需复制和操作组件本身.这该怎么做?
可能的解决方案1:将封装设置为"ViewEncapsulation.None":
这不是一个真正的解决方案,只是一种解决方法.
可能的解决方案2:在CSS中使用":: shadow"或"/ deep /":
也可以使用,但根据WebComponent规范不推荐使用它.
可能的解决方案3:使用全局CSS并覆盖组件CSS:
也可以,但它违反了shadow DOM概念.
可能的解决方案4:直接在父组件的模板中覆盖:
例:
<my-cmp [font-size]="100"></my-cmp>
Run Code Online (Sandbox Code Playgroud)
如果我们做了很多重写,那真的不合适.
可能的解决方案5:以某种方式用一个额外的样式表覆盖或扩展"@Component"定义:
这似乎是唯一正确的解决方案(至少对我而言).但我不知道该怎么做......
有什么建议吗?也许我弄错了...谢谢.
是否有可能在运行时获取TypeScript类的父类?我的意思是,例如,在装饰者中:
export function CustomDecorator(data: any) {
return function (target: Function) {
var parentTarget = ?
}
}
Run Code Online (Sandbox Code Playgroud)
我的自定义装饰器以这种方式应用:
export class AbstractClass {
(...)
}
@CustomDecorator({
(...)
})
export class SubClass extends AbstractClass {
(...)
}
Run Code Online (Sandbox Code Playgroud)
在装饰器中,我想有一个实例AbstractClass.
非常感谢您的帮助!
例如,我们有一个包含本地化字符串的文件
{
"title": "Example title",
"description": "Some text"
}
Run Code Online (Sandbox Code Playgroud)
我们假设我们还有一个带有一些自定义装饰器的组件 @I18n()
@Component({ ... })
@I18n('./my-translations.json')
export class MyAngularComponent {
}
Run Code Online (Sandbox Code Playgroud)
和模板
<h2>{{ i18n.title }}</h2>
<p>{{ i18n.description }}</p>
Run Code Online (Sandbox Code Playgroud)
是否有可能包括一个或多个外部资源(除了templateUrl和styleUrls)到组件?
我的问题是这里对另一个问题的扩展:Angular2和类继承支持
这是我的蠢货:http://plnkr.co/edit/ihdAJuUcyOj5Ze93BwIQ?p =preview
我想要做的是以下内容:
我有一些常见的功能,我的所有组件都必须使用.正如在上述问题中已经回答的那样,这可以做到.
我的问题是:我可以在基础组件中注入依赖项吗?在我的plunkr中,声明的dependency(FormBuilder)在登录到控制台时是未定义的.
import {AfterContentChecked, Component, ContentChildren, Input, QueryList, forwardRef, provide, Inject} from '@angular/core';
import { FormGroup, FormControl, Validators, FormBuilder, REACTIVE_FORM_DIRECTIVES } from '@angular/forms';
@Component({
providers: [FormBuilder]
})
export class BaseComponent {
// Interesting stuff here
@Input() id: string;
constructor(formBuilder: FormBuilder){
console.log(formBuilder);
console.log('inside the constructor');
}
}
@Component({
selector: 'child-comp2',
template: '<div>child component #2 ({{id}})</div>',
providers: [provide(BaseComponent, { useExisting: forwardRef(() => ChildComponent2) })]
})
export class ChildComponent2 extends BaseComponent {
}
@Component({ …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用此SO答案中的代码.它使用Reflect.这是一份副本:
export function CustomComponent(annotation: any) {
return function (target: Function) {
var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);
var parentAnnotation = parentAnnotations[0];
Object.keys(parentAnnotation).forEach(key => {
if (isPresent(parentAnnotation[key])) {
annotation[key] = parentAnnotation[key];
}
});
var metadata = new ComponentMetadata(annotation);
Reflect.defineMetadata('annotations', [ metadata ], target);
}
}
Run Code Online (Sandbox Code Playgroud)
首先,我遇到了这两个错误:
Property 'getMetadata' does not exist on type 'typeof Reflect'.
Property 'defineMetadata' does not exist on type 'typeof Reflect'.
Run Code Online (Sandbox Code Playgroud)
然后我跑了npm install reflect-metadata,但我不知道如何使用它.
import { Reflect } from reflect-metadata;
Module …Run Code Online (Sandbox Code Playgroud) 这个问题可能是查看问题的最快方式
我不确定使用ViewChild时它是否只是一些明显的问题,但它很奇怪.
这个plunker显示3个输入:
但是,在添加ViewChild以获取对输入的引用时,输入上的NgModel绑定将停止工作.但是您附加的任何其他绑定(如已禁用)仍将继续运行.如果您注释掉app/extended.component的第52行,它将再次绑定,但显然现在它无法集中注意力.
第一个输入/按钮显示,当您绑定到正在扩展的类中的属性时,这显然只是一个问题.
简而言之,当我通过ViewChild访问输入时,我对NgModel的绑定中断.
也就是说,给定一个属性为"someValue"的基数:绑定:
@Component({
selector: 'binding-working',
template: `<input type="text" [(ngModel)]="someValue" />`
})
export class Working extends Base<string> {
constructor() { }
};
Run Code Online (Sandbox Code Playgroud)
不绑定:
@Component({
selector: 'binding-broken',
template: `<input type="text" #imBroken [(ngModel)]="someValue" />`
})
export class Broken extends Base<string> {
@ViewChild('imBroken') input;
constructor() { }
};
Run Code Online (Sandbox Code Playgroud) 我试图使用的代码在此SO答案,它的用途ComponentMetadata。看起来它曾经是角形/芯形的,但是我想它不再可用了?
这是代码。我该怎么做才能metadata在最后一行中使用?
function ExtendComponent(annotation: any) {
return function (target: Function) {
var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);
var parentAnnotation = parentAnnotations[0];
Object.keys(parentAnnotation).forEach(key => {
if (isPresent(parentAnnotation[key])) {
// verify is annotation typeof function
if(typeof annotation[key] === 'function'){
annotation[key] = annotation[key].call(this, parentAnnotation[key]);
}else if(
// force override in annotation base
!isPresent(annotation[key])
){
annotation[key] = parentAnnotation[key];
}
}
});
var metadata = new ComponentMetadata(annotation);
Reflect.defineMetadata('annotations', [ metadata ], target);
}
}
Run Code Online (Sandbox Code Playgroud)
我在这里确实是在黑暗中拍摄,但是我在使用的角度源中找到了该测试MetadataCollector …