angular: Dynamic standalone component can not resolve FormsModule (probably others from @angular/*)
Which @angular/* package(s) are the source of the bug?
core
Is this a regression?
No
Description
I have a standalone component defined like this:
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
export const componentMetadata : Component = {
jit: true,
standalone: true,
selector: '<dynamic-component>',
imports: [
FormsModule, CommonModule
],
};
export class DynamicComponent {
public constructor() {}
....
}
Then I have component that should create dynamically, as a child, this component, with template that is coming from DB. Sample code:
import ....
@Component({
standalone: true,
selector: '<container-component>',
template: '<ng-container #content></ng-container>',
providers: [ {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ContainerComponent),
multi: true
}],
})
export class ContainerComponent implements OnInit, OnDestroy, ControlValueAccessor {
.....
@ViewChild('content', { read: ViewContainerRef, static: true })
contentContainer: ViewContainerRef;
.....
private async createContent() {
this.cleanComponentRef();
const component = await this.setupContentComponent(this.content); // we have content when we reach this method
this.componentRef = this.contentContainer.createComponent(component, {
injector: this.contentContainer.injector,
});
}
private async setupContentComponent(content: string = '') {
const defs = await import('./dynamic.component');
const currentMeta = { ...defs.componentMetadata };
currentMeta.template = content;
return Component(currentMeta)(defs.DynamicComponent);
}
private cleanComponentRef() {
if (this.componentRef) {
this.componentRef.destroy();
delete this.componentRef;
}
}
}
The content is angular template with directives like ngModel
.
The problem is that i get a lot of Can't bind to 'ngModel' since it isn't a known property of....
, but Forms module is imported in the dynamic component and should be compiled properly (IMO)
During investigation I reached a function in core.mjs function getStandaloneDefFunctions(type, imports) {
when checking for exported directives in this code:
if (!!getNgModuleDef(dep)) {
const scope = transitiveScopesFor(dep);
for (const dir of scope.exported.directives) {
dep (FormsModule) doesn’t have any exported members
scope { “schemas”: null, “compilation”: { “directives”: {}, “pipes”: {} }, “exported”: { “directives”: {}, “pipes”: {} } }
Please provide a link to a minimal reproduction of the bug
Please provide the exception or error you saw
NG0303: Can't bind to 'ngModel' since it isn't a known property of
Please provide the environment you discovered this bug in (run ng version
)
Angular CLI: 14.2.9
Node: 19.0.1 (Unsupported)
Package Manager: npm 8.19.2
OS: linux x64
Angular: 14.2.10
... animations, common, compiler, compiler-cli, core, forms
... localize, platform-browser, platform-browser-dynamic, router
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1402.9
@angular-devkit/build-angular 14.2.9
@angular-devkit/core 14.2.9
@angular-devkit/schematics 14.2.9
@angular/cdk 14.2.7
@angular/cli 14.2.9
@schematics/angular 14.2.9
rxjs 7.5.7
typescript 4.7.4
Anything else?
This is happening when aot: true
in angular.json
When aot: false
, then all is working but then template translations (all tags in .html files having i18n
attribute) are not expanded, but all @localize'text'
messages are. Probably this is for another issue / discussion
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 17 (8 by maintainers)
I finally succeeded to get hybrid model working.
For our personal case we need not so much - just
NgModel
,NgIf
andNgFor
I created a module with following code (we are at angular 15 where NgIf and NgFor are standalone, may be for older versions it should be tuned)
Our project now is compiled with
aot: true
, dynamic components havejit: true
and all they import theJitModule
I don’t know how long this will work and if it will change in the future versions, but it is a live-saver for the time of writing