angular - Angular2/4: Overstyr komponent fra en annen modul
Jeg bruker Angular 4.3, TypeScript 2.2
Jeg vil lage flere applikasjoner (nettsteder) basert på samme kodebase. Alle nettsteder vil være stort sett identiske, men noen av dem kan ha litt ekstra/annerledes logikk/maler.
Min idé er å lage en kjernemodul (som hovedsakelig inneholder komponenter), og deretter la applikasjonene bruke den modulen for å bygge videre på den, og overstyre etter behov:
- stilene
- malene (erstatt malen helt, eller bare endre en del av den)
- Hvordan kan jeg overstyre komponentene som brukes i kjerne-modulen?
Jeg klarte bare å overstyre komponentene som brukes eksplisitt i rutingen, men jeg kan ikke overstyre barnekomponenter som kalles direkte i malene til Core-modulen. Må jeg injisere disse komponentene dynamisk?
- Når man arver en komponent, er det mulig å bare overskrive en del av forelderens mal?
Jeg antar at hver maldel som må overstyres, må endres til en komponent i kjerne-modulen (og deretter tilbake til spørsmål #1 for å bruke arvet komponent i barneappene)
Takk
Svar #1
Spørsmål #1
Her er en løsning som fungerte for meg
Trinn 1
Jeg la alle mine kjernekomponenter i en kjerne-modul i en kjerne-app.
Trinn 2
Jeg erklærte følgende CustomModule-funksjon i kjerneappen
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);
};
}
Trinn 3
I en annen applikasjon opprettet jeg et annet modul kalt InheritedModule. Jeg opprettet komponenter som arver fra komponentene i CoreModule. Den arvede komponenten må ha samme navn og samme selektor som foreldreaktiviteten.
Trinn 4
Jeg fikk InheritedModule til å arve fra CoreModule. InheritedModule ble deklarert med CustomModule-annotasjonen ovenfor (ikke bruk NgModule)
Den nye modulen bør erklære og eksportere komponentene som ble opprettet i trinn 3
@CustomModule({
declarations: [ Component1, Component2 ],
exports: [ Component1, Component2],
bootstrap: [AppComponent]
})
export class InheritedModule extends CoreModule
{
}
Trinn 5
Importer InheritedModule i barneappen.
Det tilpassede modulfunksjonen vil slå sammen annotasjonene til de to modulene, og erstatte CoreModules komponenter med InheritedModules komponenter når de har samme navn
Spørsmål #2
Jeg antar at jeg må erstatte deler av HTML-maler med små komponenter hver gang jeg vil overstyre en del av HTML-en fra kjerneappen. Jeg lar svaret være uakseptert foreløpig i tilfelle noen får en bedre idé
