I'm using angular 4.3, typescript 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.
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. 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)
Thanks
Question #1
Here is a solution that worked for me
Step 1
I put all my core components in a core module in a core app.
Step 2
I declared the following CustomModule fonction in the core app
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 a different module called InheritedModule, I created components that inherit from the components in the 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 was declared with the CustomModule annotation above (do not use NgModule)
That 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 the child app.
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
Question #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. I'll leave the answer unaccepted for now in case somebody gets a better idea
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With