Angular2 / 4: override a component from another module

I am using angular 4.3, typescript 2.2

I want to create several applications (websites) based on the same code base. All websites will be pretty much identical, but some of them may have some additional / different logc / templates.

My idea is to create a main module (containing mainly components), and then use applications to use this module and reload if necessary: ​​- styles - templates (completely replace the template or just change part of it)

  • How can I override the components used in the main module?

I managed to redefine the components that are explicitly used in routing, but I can not redefine the child components called directly in the Core module templates. Do I need to dynamically inject these components?

  1. When inheriting a component, is it possible to override part of the parent template?

I think that every part of the template that needs to be redefined should be replaced with a component in the main module (and then to question No. 1 use the inherited component in child applications)

thanks

+5
source share
1 answer

Question number 1

Here is the solution that worked for me

Step 1

I put all the main components in the main module in the main application.

Step 2

I announced the following CustomModule setup in the main application

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

In another application, I created another module called InheritedModule, I created components that inherit from components in CoreModule. An inherited component must have the same name and the same selector as the parent component.

Step 4

I made InheritedModule an inheritance from CoreModule. InheritedModule was declared with CustomModule annotation above (do not use NgModule)

This new module should declare and export the components created in step 3.

 @CustomModule({ declarations: [ Component1, Component2 ], exports: [ Component1, Component2], bootstrap: [AppComponent] }) export class InheritedModule extends CoreModule { } 

Step 5

Import InheritedModule in a child application.

What the user module function will do is combine the annotations of the two modules and replace the CoreModule components with the InheritedModule components when they have the same name

Question number 2

I think I will have to replace the bits of the html templates with tiny components when I want to override the html part from the main application. I will leave the answer unacceptable at the moment if someone gets a better idea

+2
source

Source: https://habr.com/ru/post/1269983/


All Articles