New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature Request] Automatic Inclusion of Component in Entry Components #28826
Comments
Yeh, it is a bit of extra coding today. We won't be able to change it in the current version of Angular but the good news is that ivy version of the compiler pipeline / runtime |
Very cool! It seems like the reason Ideally stuff like this works like this:
|
Another option that also wouldn't be intrusive is to do it like with providedIn and just define it in the decorator?
|
@Airblader We have already done it by introducing a new customized decorator. // EntryComponentDecorator.ts
import { TypeDecorator } from '@angular/core';
import { makeDecorator } from './decoratorHelper';
const decoratorName = 'EntryComponent';
export interface EntryComponentDecorator extends DecoratorBase {
(): TypeDecorator;
new (): TypeDecorator;
}
export const EntryComponent = makeDecorator(decoratorName) as EntryComponentDecorator;
EntryComponent.decoratorName = decoratorName; // decoratorHelper.ts: Various utils
import { Type } from '@angular/core';
import * as decoratorsHack from '@angular/core/esm2015/src/util/decorators';
// https://github.com/angular/angular/blob/885f1af509eb7d9ee049349a2fe5565282fbfefb/packages/core/src/util/decorators.ts#L38
export const ANNOTATIONS = decoratorsHack.ANNOTATIONS as
typeof import ('@angular/core/src/util/decorators').ANNOTATIONS;
// makeDecorator is the "angular way" to create decorator class, but is inaccessible at user-code. Hack it out.
// https://github.com/angular/angular/blob/885f1af509eb7d9ee049349a2fe5565282fbfefb/packages/core/src/util/decorators.ts#L45
export const makeDecorator = decoratorsHack.makeDecorator as
typeof import ('@angular/core/src/util/decorators').makeDecorator;
/**
* Gets all decorators (annotations) decorated for specified class
* @param clazz The type of the class ( function )
* @param annoName Decorator (annotation) name. Returns all decorators if not specified
*/
export function getAnnotationsOfClass<TAnno>(clazz: Type<any>, annoName?: string) {
if (ANNOTATIONS in clazz) {
let annos = clazz[ANNOTATIONS] as TAnno[];
if (annoName) {
annos = annos.filter((anno: any) => anno.ngMetadataName === annoName);
}
return annos;
}
return [];
}
/**
* Gets all classes which decorated by specified decorator (annotation)
* @param module The module object (usually get by `import * as ModuleObject from 'module')
* @param annoName Decorator (annotation) name
*/
export function getClassesOfAnnotations<TAnno>(module: { [key: string]: any }, annoName: string) {
return Object.values(module)
.filter(clazz => typeof clazz === 'function')
.map(clazz => ({
clazz,
annos: getAnnotationsOfClass<TAnno>(clazz, annoName),
}))
.filter(({ annos }) => annos.length);
} // DecoratorBase.d.ts
interface DecoratorBase {
decoratorName: string;
} Usage: import * as components from './components';
import * as decorators from './decorators';
@NgModule({
entryComponents: [
...getClassesOfAnnotations<void>(components, decorators.EntryComponent.decoratorName).map(({ clazz }) => clazz),
],
})
export class AppModule {} @EntryComponent()
@Component({
selector: 'my-component',
template: '...',
})
export class MyComponentComponent {
} Other decorators can be done in the same way // https://github.com/angular/angular/blob/885f1af509eb7d9ee049349a2fe5565282fbfefb/packages/core/src/di/interface/provider.ts#L366
import { Provider as ProviderType, TypeDecorator } from '@angular/core';
import { makeDecorator } from './decoratorHelper';
const decoratorName = 'Provider';
export interface ProviderDecorator extends DecoratorBase {
(obj?: ProviderType): TypeDecorator;
new (obj?: ProviderType): TypeDecorator;
}
export const Provider = makeDecorator<ProviderType>(decoratorName) as ProviderDecorator;
Provider.decoratorName = decoratorName; @NgModule({
providers: [
...[
...getClassesOfAnnotations<Provider>(components, decorators.Provider.decoratorName),
].map(({ clazz, annos }) => annos[0].hasOwnProperty('provide') ? annos[0] : clazz),
],
}) |
Just realized that it's not enough to declare a component in
It has to be included in both
This seems redundant and is not DRY. Also cross referenced that this is the case on SO. |
https://ng-run.com/edit/bY1pxzWwKrEqPOjevXnS demonstrates that |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
馃殌 feature request
Automatic inclusion / management of component in entry components.
Relevant Package
Angular/core angular/compiler
Description
When creating a component / host view as documented here:
https://medium.com/@ole.ersoy/creating-a-host-view-2dfc895a384b
We have to remember to include the component in the entry components. Ideally the Angular compile process would do a code scan and add this for us automatically when the code fits the pattern that requires this.
Or Angular just does away with entry components and builds in dynamic component support by default in all modules. I don't think it's going to add much weight, if any.
Describe the solution you'd like
Ideally we should not have to remember to do this step. Angular should just know how to make dynamic components.
Describe alternatives you've considered
Do the extra step, but this is not a DRY approach. For example if while refactoring someone removes the dynamic component creation from the module, they also have to remember to update the entry components array.
The text was updated successfully, but these errors were encountered: