Reputation: 187
I have been struggling to find a solution to my task - when I remove attachment from the list of attachment object belonging to the comment, I want to set the focus to the nearest attachment left in the array - if the array is blank, I want to set the focus to the parent comment component
Child Edit-comment html file
<div *ngFor="let attachment of comment?.attachments; let index = index">
<h4>{{ attachment.filename }}</h4>
<Button [attr.id]="'remove-btn-' + index" (click)="deleteAttachment(attachment)">Remove attachment</Button>
</div>
Child Edit-comment ts file
export class EditCommentComponent {
@Input() comment: Comment;
@Output() deleteCommentAttachment = new EventEmitter<CommentAttachment>();
public deleteAttachment(attachment: CommentAttachment): void {
this.deleteCommentAttachment.emit(attachment);
}
Parent list-comments html file
<app-edit-comment
[comment]="comment"
(deleteCommentAttachment)="deleteCommentAttachment($event)"
></app-edit-comment>
Parent list-comments ts file
export class ListCommentsComponent {
public comment: Comment;
// validationProtocolP - this is a variable holding all the mock data for
comments
public deleteCommentAttachment(attachment: CommentAttachment): void {
// logic for deleting comment attachment
// logic to set focus -
const attachmentIndex = this.validationProtocolP.comments[commentIndex].attachments.findIndex((at) => at.id === this.attachment.id);
if (this.comment.attachments[attachmentIndex - 1]) {
setTimeout(() =>
this.setFocus(document.getElementById('remove-att-btn-' + (attachmentIndex - 1))),
);
} else if (this.comment.attachments[attachmentIndex + 1]) {
setTimeout(() =>
this.setFocus(document.getElementById('remove-att-btn-' + attachmentIndex)),
);
} else {
console.log('Focus set to parent of attachments');
}
public setFocus(el: HTMLElement): void {
const focusElement = (el.previousSibling as HTMLElement) || (el.nextSibling as HTMLElement);
if (focusElement) {
focusElement.focus();
}
}
}
Upvotes: 0
Views: 1619
Reputation: 18905
You can pass references to DOM elements and use nextSibling
or previousSibling
to focus these elements.
This is an example of the basic principle (https://stackblitz.com/edit/angular-ivy-wkwgsl?file=src/app/app.component.ts). You can adapt to your specific logic:
@Component({
selector: 'my-child',
template: `<div><button (click)="remove.emit()">{{ comment }}</button></div>`,
})
export class ChildComponent {
@Input() comment: string;
@Output() remove = new EventEmitter();
}
@Component({
selector: 'my-app',
template: `
<div #parent>
<div #child *ngFor="let c of children; let index = index">
<my-child [comment]="c" (remove)="remove(index, child, parent)"></my-child>
</div>
</div>`,
})
export class AppComponent {
children = ['1', '2', '3'];
remove(index: number, child: HTMLElement, parent: HTMLElement) {
this.children.splice(index, 1);
const focusElement =
(child.previousSibling as HTMLElement) ||
(child.nextSibling as HTMLElement) ||
parent;
if (focusElement && typeof focusElement.focus === 'function') {
focusElement.focus();
}
}
}
Upvotes: 1