Modal component data binding pattern is impractical
See original GitHub issueBug description:
The pattern used to pass data to modal components is impractical and I think it could be enhanced to avoid common mistakes.
As described in the docs, you can pass data to your modal as follows:
const modalRef = this.modalService.open(NgbdModalContent);
modalRef.componentInstance.name = 'World';
This works fine, but has two problems:
-
It causes an
ExpressionChangedAfterItHasBeenCheckedError
error when the template usesname
in structural directives like*ngIf
,*ngFor
etc.Workaround:
Inject public cdref: ChangeDetectorRef
in your modal component constructor and doing:
const modalRef = this.modalService.open(NgbdModalContent);
modalRef.componentInstance.name = 'World';
modalRef.componentInstance.cdref.detectChanges();
- With this pattern, the modal component’s lifecycle hooks are executed before the binding is done. In other words,
ngOnInit
is executed before'World'
is binded to propertyname
ofmodalRef
.
Workaround:
Ignore lifecycle hooks and define a custom method bindData(data: any)
as follows:
export class NgbdModalContent implements OnInit {
@Input() name;
constructor(
public activeModal: NgbActiveModal,
public cdref: ChangeDetectorRef,
) {
}
bindData(data: { name?: any }): void {
// Bind your data here
this.name = data.name;
// Force change detection to avoid ExpressionChangedAfterItHasBeenCheckedError
this.cdref.detectChanges();
/*
* Here you can put your logic
* Your logic must be placed AFTER triggering change detection, otherwise
* directives and components will not be updated correctly.
*/
}
ngOnInit(): void {
// This callback is not really useful as it is executed before bindings are applied
}
}
then just bind the data like so:
const modalRef = this.modalService.open(NgbdModalContent);
(modalRef.componentInstance as NgbdModalContent).bindData({name: 'World'});
Be aware that this will work only in the order I mentioned:
- Bind the data
- Trigger change detection
- Execute your own logic
Version of Angular, ng-bootstrap, and Bootstrap:
Angular: 6.0.6
ng-bootstrap: 3.0.0
Bootstrap: 4.1.1
Issue Analytics
- State:
- Created 5 years ago
- Reactions:17
- Comments:5 (1 by maintainers)
Top Results From Across the Web
cant bind data between object to a modal - Stack Overflow
i'm trying to bind data between a modal that it content is a form for editing data. i'm using the ng-model directive ,...
Read more >ion-popover - Ionic Framework
With a two way data binding, the popover needs to concern itself with both the boolean value as well as the existence of...
Read more >How to build a Reusable Vuejs modal component - Medium
I'm going to build a Modal component and reusable in every page. ... We need to add the new data binding in the...
Read more >S N O Text Tags Dominant Topic Topic Terms URL Label No. of ...
accordingly frame modal dialog java;swing;design- patterns;jframe. 1 output, text, document, format, button, copy, account, original,.
Read more >US8127237B2 - Active business client - Google Patents
The UI component enables functionality in the client device related to ... generating the business context data includes binding a data component to...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I agree using
componentInstance
this way has many pitfalls and I do not encourage it in codebases I work on.This is how I work around this:
This way passed data is typed, there is no outside component instance modifications and init lifecycle hook can be used for initialization as expected. Forgetting to provide the data results with error which is a nice touch.
Additionaly, in some cases using opening component injector as
parent
when creating modal component injector may be useful.It’s also worth mentioning that ngOnChanges doesn’t get called at all.