primeng
primeng copied to clipboard
#FocusTrap for nested DynamicDialogs still not working
Tab keys not working when i open dynamic dialog from another dynamic dialog, it stuck on close button so if i focus on control by using mouse keys and then i press tab key it focus again close button. I am using 9.1.5-lts version
hey! what is the issue can u please explain
Hey!! problem is that when we open a dynamic dialog from a dynamic dialog then focus controls using tab key stuck on the 1st dialog. expected behavior should have been like focus on last open dynamic dialog
Btw thanks for your reply
This issue is also affecting the project I am working on.
Trying to use the keyboard to tab through field when working on a Dynamic Dialog on-top of another Dynamic Dialog does not work.
Trying to use the "FocusTrap" module on my second Dynamic Dialog does not address the issue.
I have the same problem. Here is my workaround:
export class FirstModalComponent {
constructor(
private dialogService: DialogService,
public dynamicDialogRef: DynamicDialogRef,
) {
}
public openSecondModal(): void {
// open the second modal
const secondModalRef = this.dialogService.open(SecodModalComponent);
// get DynamicDialogComponent instance for the current/first modal
const dynamicDialogComponent = this.dialogService.dialogComponentRefMap.get(this.dynamicDialogRef).instance;
// unbind tab/esc buttons listeners
dynamicDialogComponent.unbindGlobalListeners();
// when the second modal is closed/destroyed then
secondModalRef.onDestroy.pipe(first()).subscribe(() => {
// reinitialize the first modal
dynamicDialogComponent.moveOnTop(); // we need this for properly Esc button handler
dynamicDialogComponent.bindGlobalListeners(); // bind tab/esc buttons listeners
dynamicDialogComponent.focus(); // apply [autofocus] if any
});
}
}
I have the same problem. Here is my workaround: // when the second modal is closed/destroyed then secondModalRef.onDestroy.pipe(first()).subscribe(() => {
What is the first() thing you're calling in the pipe? I'm trying your workaround but this isn't working for me.
Wait, apparently it's part of rxjs. But this part:
this.dialogService.dialogComponentRefMap.get(this.dynamicDialogRef)
is coming back as undefined for me.
@techmaster242
What is the first() thing you're calling in the pipe? I'm trying your workaround but this isn't working for me.
Wait, apparently it's part of rxjs. But this part:
.pipe(first())
- this is for a subscription canceling (unsubscribing), you can do this in different ways, it is not necessary for this example. And yes, it is from rxjs
.
this.dialogService.dialogComponentRefMap.get(this.dynamicDialogRef)
As I mentioned in the comment, it is to "get DynamicDialogComponent instance for the current/first modal", without this line, we can't do all the things below. Because this.dynamicDialogRef
doesn't have the necessary methods, it is like a wrapper for a DynamicDialogComponent instance.
Same problem
I also have the same problem
To work you need to add the DialogService into app.module providers
I am also experiencing the tab problem - in a dynamic dialog, opened from a dynamic dialog, all tabbing wants to go to the close button (X). If I turn that off, all tabbing goes to the first input control.
was this problem resolved?
not found any solution that's why I avoid nested dialog solution in my application
@cagataycivici This problem is really important, we have a lot of feedback from our clients on our projects on this subject. Sometimes we don't have the choice to open 2 DynamicDialog. Would it be possible to fix this problem for a 13.x version?
Thanks in advance
Any updates on this issue?
I'm having the same problem with pressing enter or space keys
I found a posible solution, apply when open a DynamicDialog inside another DynamicDialog
export class DynamicDialog2 implements OnInit { ngOnInit{ ... this.dialogService.dialogComponentRefMap.forEach(dialog => { if(dialog.instance.childComponentType.name.includes("--name of the entity --")){ dialog.instance.focus(); } else{ dialog.instance.unbindGlobalListeners(); // close for the previous instance } }); } }
I found a posible solution, apply when open a DynamicDialog inside another DynamicDialog
export class DynamicDialog2 implements OnInit { ngOnInit{ ... this.dialogService.dialogComponentRefMap.forEach(dialog => { if(dialog.instance.childComponentType.name.includes("--name of the entity --")){ dialog.instance.focus(); } else{ dialog.instance.unbindGlobalListeners(); // close for the previous instance } }); } }
Unfortunatly, this workaround does not work for me.
Any updates on this issue ?
please help us! any solution?
The workaround did not work for me neither.
But I've found a solution. Here is the relevant part :
@Component({
templateUrl: './first-dialog.component.html',
providers: [DialogService]
})
export class FirstDialogComponent {
constructor(
private refDialogComponent: DynamicDialogComponent,
private dialogService: DialogService
) { }
public openSecondDialog(): void {
this.refDialogComponent.unbindDocumentKeydownListener();
const subref = this.dialogService.open(SecondDialogComponent);
subref.onDestroy.pipe(
take(1),
tap(() => this.refDialogComponent.bindDocumentKeydownListener())
).subscribe();
}
}
The trick is to get a reference to the nearest DynamicDialogComponent
(in the constructor), which is in fact the first dialog.
Then, before opening the second dialog, unbind the key listeners from the first dialog and re-bind them when the second dialog is destroyed.
Hi,
So sorry for the delayed response! Improvements have been made to many components recently, both in terms of performance and enhancement. Therefore, this improvement may have been developed in another issue ticket without realizing it. You can check this in the documentation. If there is no improvement on this, can you reopen the issue so we can include it in our roadmap? Please don't forget to add your feedback as a comment after reopening the issue. These will be taken into account by us and will contribute to the development of this feature. Thanks a lot for your understanding!
Best Regards,
Hi,
The problem is still not solved with the latest version of PrimeNG 14.2.1 The solution is in this ticket : https://github.com/primefaces/primeng/pull/12039 Could you merge for the next release? Thanks
Just discovered this issue in my app, looking for a fix. Thanks @mselerin for pushing the fix and workaround! Hope they will merge this soon.
Hi @mertsincan, @cagataycivici Would it be possible to merge this issue which works perfectly. We've been waiting for this fix for several years. Thanks in advance
I created this service, all you need is to just open every dialog with this.
So change DialogService
to TabbedDialogService
import { Injectable, Type } from '@angular/core';
import {
DialogService,
DynamicDialogComponent,
DynamicDialogConfig,
DynamicDialogRef,
} from 'primeng/dynamicdialog';
import { first } from 'rxjs/operators';
@Injectable({
providedIn: 'root',
})
export class TabbedDialogService {
constructor(private dialogService: DialogService) {}
currentDialogRef: DynamicDialogRef | null = null;
open(
componentType: Type<any>,
config: DynamicDialogConfig
): DynamicDialogRef {
let currentDialogComponent: DynamicDialogComponent | undefined;
if (this.currentDialogRef) {
currentDialogComponent = this.dialogService.dialogComponentRefMap.get(
this.currentDialogRef
)?.instance;
currentDialogComponent?.unbindGlobalListeners();
}
const lastDialogRef = this.currentDialogRef;
const dialogRef = this.dialogService.open(componentType, config);
this.currentDialogRef = dialogRef;
dialogRef.onDestroy.pipe(first()).subscribe(() => {
// reinitialize the first modal
if (currentDialogComponent) {
currentDialogComponent.moveOnTop(); // we need this for properly Esc button handler
currentDialogComponent.bindGlobalListeners(); // bind tab/esc buttons listeners
currentDialogComponent.focus(); // apply [autofocus] if any
}
this.currentDialogRef = lastDialogRef;
});
return dialogRef;
}
}
@djay1977 I have the same problem, but DynamicDialogComponent is a component, that is, I can't inject a component into a class, is there any solution for this?
the solution is here : https://github.com/primefaces/primeng/pull/12039
for me it still doesn't work :( (version 16.5.0)
En la versión 17.3.3 yo hice lo siguiente :
1 .Desde MenuComponent abro el primer dialog que tiene el componente FloatRequestsComponent :
` public openRequestsFloatingModal() : void {
const dialogRef = this.dialog.open(FloatRequestsComponent, {
styleClass: 'app-full-bleed-dialog',
style: {
minWidth: '60vw',
minHeight: '44vh',
maxWidth: '80vw',
maxHeight: '60vh',
hasBackdrop: false,
autoFocus: false},
modal: true,
draggable: true,
resizable: true,
header: 'Solicitudes'
});
}`
- Abro el segundo modal NewRequestsComponent
public openNewRequestModal() : void {
this.compOpened[index].value = true;
const dialogRef = this.dialog.open(NewRequestComponent, {
styleClass: 'app-full-bleed-dialog',
style: {
'min-height': '60vh',
'max-height': '80vh',
'min-width': '45vw',
'max-width': '50vw'} ,
modal: false,
header: 'Nueva solicitud',
draggable: true,
resizable: true,
data: {
new: true
}
}); }
- En el segundo dialogo abierto deberías colocar este código en el ngOnInit (Ojo donde dice newRequestComponent debe tener el nombre del componente del 2 dialog):
this.dialogService.dialogComponentRefMap.forEach(dialog => {
if (dialog.instance.childComponentType.name.includes("NewRequestComponent")) {
dialog.instance.focus();
}
else {
dialog.instance.unbindGlobalListeners(); // cerrar para la instancia anterior
}
});
Saludos , espero que les sirva.