Comments (4)
@ryanbonial you can always wrap those components in your own component that will proxy [(ngModel)]
through the Input and Output.
from ng-dynamic-component.
You have to keep in mind that dynamically created components will not have inputs and outputs to be attached in the DOM and as a consequence your ngModel input wont tell Angular to bind ngModel to the corresponding value accessor - you have to take care about it manually.
So I added 1 more input ngModel
and 1 output ngModelChange
in order to simulate what angular will do.
Secondly if you want to have true 2 way binding you cannot directly update ngModel value because it will loose reference to the bounded component instance, instead you have to use dot construct
like inputs.ngModel
where inputs
property will be bound to dynamic component inputs.
Please refer to updated plunkr for working example.
from ng-dynamic-component.
Thanks for the explanation and updated plunkr. It is a shame that ngModel and ngModelChange have to be implemented manually. I can add the additional Input() and Output() for my own components, but it will be tougher to use 3rd party components that use ngModel.
from ng-dynamic-component.
I solved it by wrapping the control value accessor components in a component of my own. The final class base class for these components look like this:
export class FormFieldsComponent implements AfterViewInit, OnDestroy {
@ViewChildren(NgModel)
formControllers: QueryList<NgModel>;
@Input()
public form: NgForm;
private addedFormControllers: NgModel[];
private formControllerChangeSub: Subscription;
constructor() {
this.addedFormControllers = [];
}
ngAfterViewInit(): void {
this.setupFormControllers();
this.formControllerChangeSub = this.formControllers.changes.subscribe(
this.setupFormControllers.bind(this)
);
}
private setupFormControllers(): void {
this.resetFormControllers();
if (this.formControllers && this.formControllers.length) {
this.formControllers.forEach(control => {
control.name = `${ control.name }_${ Date.now() }`;
this.addedFormControllers.push(control);
this.form.addControl(control);
});
}
}
private resetFormControllers(): void {
if (this.addedFormControllers) {
this.addedFormControllers.forEach(
control => this.form.removeControl(control)
);
this.addedFormControllers = [];
}
}
ngOnDestroy(): void {
this.resetFormControllers();
this.formControllerChangeSub.unsubscribe();
}
}
Then I have another base class for my angular component that is placed between my angular component and the base class above. That class looks like this:
export class CustomFieldInputBase<T extends CustomField> extends FormFieldsComponent implements OnDestroy {
@Input()
customField: T;
@Input()
model: any;
constructor() {
super();
}
ngOnDestroy(): void {
super.ngOnDestroy();
}
}
The input model is an object i will do two way bindings on. The input customField only contains data about the field I'm rendering containing it's name and so on.
An example of my angular component class looks like this:
@Component({
selector: 'custom-string-field-input',
encapsulation: ViewEncapsulation.None,
providers: [],
templateUrl: './custom-string-field-input.component.html',
styleUrls: ['./custom-string-field-input.component.sass']
})
export class CustomStringFieldInputComponent extends CustomFieldInputBase<CustomStringField> implements OnInit, OnDestroy {
constructor(
) {
super();
}
ngOnInit(): void {
}
ngOnDestroy(): void {
super.ngOnDestroy();
}
}
And its HTML:
<input name="{{ customField.name }}"
placeholder="{{ customField.label }}{{ customField.required ? '*' : '' }}"
class="{{ customField.name }}-input"
[(ngModel)]="model[customField.name]"
[attr.empty]="(!model[customField.name] || !model[customField.name].trim()) ? '' : undefined"
[required]="customField.required"
autocomplete="off">
The base class FormFieldsComponent registers any children of NgModel to the form (inputed to the same class), after that it all should function as usual.
This may be quite overwhelming for some, but I didn't have much time to post this. Hopefully it can help someone :)
from ng-dynamic-component.
Related Issues (20)
- Question about dynamic templates HOT 2
- Support RxJS ^7.4.0 HOT 2
- Support for Angular 14 HOT 7
- Need add rxjs 7 support for version 9.x.x HOT 14
- Building app with angular 13 leads to compile error HOT 6
- Outputs initialized after inputs which leads to missed events triggered synchronously from constructors/setters HOT 2
- Cannot access 'IoService' before initialization HOT 8
- Backwards compatibility with Angular 13 in minor update v10.x.x is broken HOT 1
- [Question] How to call functions mentioned in dynamic components HOT 2
- Support for Angular 15 HOT 4
- Ability to provide ngModuleRef when creating component HOT 4
- [BUG] `IoEventContextToken` is not exported HOT 3
- Unknown input error after updating from no-barrels version [Bug] HOT 1
- Property 'withComponents' does not exist on type 'typeof DynamicModule'. HOT 1
- Support angular 14 HOT 1
- Component not support nested HOT 2
- [Bug] HOT 2
- Support for Angular 16 HOT 3
- Angular 17 support HOT 4
- [Bug] Remove ndc-dynamic from the dom using flex gap or add display none HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ng-dynamic-component.