[英]Angular2/4 : Override component from another module
I'm using angular 4.3, typescript 2.2 我正在使用棱角4.3,打字稿2.2
I want to create multiple applications (websites) based on the same codebase. 我想基于相同的代码库创建多个应用程序(网站)。 All websites will be pretty much identical, but some of them might have some additional/different logc/templates. 所有网站都完全相同,但其中一些可能有一些额外的/不同的logc /模板。
My idea is to create a core Module (containing mainly components), and then have the applications use that module to build upon it, and overload as needed: - the styles - the templates (replace completely the template, or just modify a part of it) 我的想法是创建一个核心模块(主要包含组件),然后让应用程序使用该模块构建它,并根据需要重载: - 样式 - 模板(完全替换模板,或只修改模板的一部分)它)
I only managed to override the components wich are used explicitely in the routing, but I cannot override child components called directly in the templates of the Core module. 我只设法覆盖路由中明确使用的组件,但我不能覆盖在Core模块的模板中直接调用的子组件。 Do I need to inject these components dynamically? 我是否需要动态注入这些组件?
I guess each template part that needs to be overriden would have to be changed to a component in the core module (and then back to question #1 to use inherited component in the child apps) 我想每个需要重写的模板部分都必须更改为核心模块中的一个组件(然后回到问题#1以使用子应用程序中的继承组件)
Thanks 谢谢
Question #1 问题#1
Here is a solution that worked for me 这是一个适合我的解决方案
Step 1 第1步
I put all my core components in a core module in a core app. 我将所有核心组件都放在核心应用程序的核心模块中。
Step 2 第2步
I declared the following CustomModule fonction in the core app 我在核心应用程序中声明了以下CustomModule功能
declare var Reflect : any;
export function CustomModule(annotations: any)
{
return function (target: Function)
{
let parentTarget = Object.getPrototypeOf(target.prototype).constructor;
let parentAnnotations = Reflect.getMetadata("annotations", parentTarget);
let parentAnnotation = parentAnnotations[0];
Object.keys(parentAnnotation).forEach(key =>
{
if (parentAnnotation[key] != null)
{
if (typeof annotations[key] === "function")
{
annotations[key] = annotations[key].call(this, parentAnnotation[key]);
}
else if (typeof Array.isArray(annotations[key]))
{
let mergedArrayItems = [];
for (let item of parentAnnotation[key])
{
let childItem = annotations[key].find(i => i.name == item.name);
mergedArrayItems.push(childItem ? childItem : item);
}
annotations[key] = mergedArrayItems;
}
else if (annotations[key] == null)
{ // force override in annotation base
annotations[key] = parentAnnotation[key];
}
}
});
let metadata = new NgModule(annotations);
Reflect.defineMetadata("annotations", [metadata], target);
};
}
Step 3 第3步
In another application, I created a different module called InheritedModule, I created components that inherit from the components in the CoreModule. 在另一个应用程序中,我创建了一个名为InheritedModule的不同模块,我创建了从CoreModule中的组件继承的组件。 The inherited component must have the same name and the same selector as the parent component. 继承的组件必须与父组件具有相同的名称和相同的选择器。
Step 4 第四步
I made InheritedModule inherit from the CoreModule. 我使InheritedModule继承自CoreModule。 InheritedModule was declared with the CustomModule annotation above (do not use NgModule) 使用上面的CustomModule注释声明了InheritedModule(不要使用NgModule)
That new module should declare and export the components created in Step 3 该新模块应声明并导出在步骤3中创建的组件
@CustomModule({
declarations: [ Component1, Component2 ],
exports: [ Component1, Component2],
bootstrap: [AppComponent]
})
export class InheritedModule extends CoreModule
{
}
Step 5 第5步
Import InheritedModule in the child app. 在子应用程序中导入InheritedModule。
What the custom module function will do is merge annotations of the 2 modules, and replace CoreModule's components by InheritedModule's components when they have the same name 自定义模块函数将做的是合并2个模块的注释,并在它们具有相同名称时用InheritedModule的组件替换CoreModule的组件
Question #2 问题2
I guess I'll have to replace bits of html templates with tiny components whenever I want to override part of the html from the core app. 我想每当我想要从核心应用程序覆盖部分html时,我将不得不用微小的组件替换一些html模板。 I'll leave the answer unaccepted for now in case somebody gets a better idea 我暂时不接受答案,以防有人得到更好的想法
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.