Issue
I have a component for a modal window that is customisable. The modal can have any number of buttons, that will do any number of different tasks and functions.
Because the buttons have customisable text and styling as well as the callback, I want to pass through an interface that looks similar to this:
enum ButtonType {
basic = 'basic',
primary = 'primary',
tertiary = 'tertiary',
}
export interface IModalButton {
text: string;
type?: ButtonType;
callback: any; // Not sure what to set this to, it didn't like being set to EventEmitter
}
To then pass through a simple close button as an example, I have these properties in a parent class:
modalContent = '';
modalTitle = '';
isVisible = false;
buttons: IModalButton[] = [
{
callback: this.toggleVisibility,
text: 'Close',
},
];
toggleVisibility() {
this.isVisible = !this.isVisible;
}
And then I'm passing those properties through to the child like so:
<exp-modal *ngIf="isVisible" [title]="modalTitle" (close)="toggleVisibility();" [buttons]="buttons">
<p>{{ modalContent }}</p>
</exp-modal>
The problem I have is, that when I call the function in the child component, it runs it as though it is in the child component (it changes isVisible in the child component). I also can't work out how this can be done with event emitters either because my buttons
array needs to sort of be passed in as both @Input()
and @Output()
. There is an actual separate close button at the top right that will always be there and currently does work, so I know toggleVisibility();
itself is working fine.
So my question is, how can I pass through an array of objects to a child component where the callback to a parent component is nested within the objects?
Various different things that I've tried can be found here: https://stackblitz.com/edit/modal-buttons-test
Solution
I managed to get around it by passing through a separate output to the child.
Parent HTML:
<exp-modal *ngIf="isVisible" [title]="modalTitle" [buttons]="buttons" (close)="toggleVisibility()"
(buttonEvent)="modalService.executeCallback($event)">
<p>{{ modalContent }}</p>
</exp-modal>
Parent Typescript:
isVisible = false;
buttons: IModalButton[] = [
{
callback: this.toggleVisibility.bind(this),
text: 'Close',
},
];
constructor(
readonly modalService: ModalService,
) { }
toggleVisibility() {
this.isVisible = !this.isVisible;
}
Service:
export class ModalService {
executeCallback(callback: Function) {
callback();
}
}
Child HTML:
<button *ngFor="let button of buttons; index as i" class="eds-button eds-button.{{button.type}}"
(click)="sendCallback(button.callback);">
<span class="eds-button_#label">{{button.text}}</span>
</button>
Child Typescript:
@Input() buttons: IModalButton[];
@Output() buttonEvent = new EventEmitter();
sendCallback(callback: Function) {
this.buttonEvent.emit(callback);
}
The full solution has been updated on the stackblitz: https://stackblitz.com/edit/modal-buttons-test
Answered By - Jamie Barker
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.