אני חושב שפתרון ג'נרי כאן זה רעיון טוב ונכון. זו תשובה ארוכה קצת ולכן אני אסביר את עצמי בקצרה, במידה ולא הבנתם משהו, תשאלו חופשי (אם מרגיש לכם יותר בנח, אפשרי בפרטי).
אני מניח שלכל פריט מידע יש type (ואם אין, כדאי להוסיף). אני חושב שהכי פשוט יהיה ליצור enum של types (לכל סוג של פריט מידע יש ערך שונה). לדוגמה:
PHP:
export enum DataItemType {
Animal = 1,
Human = 2,
Machine = 3
}
בנוסף, הייתי יוצר class שמגדיר כפתור:
PHP:
export class ButtonMetaData<TDataItem> {
constructor (public title: string, public cssClass: string,
private _onClickHandler: (dataItem: TDataItem) => void,
private _selectionDataKeeper: ISelectionDataItemKeeper) {
}
public onClick(): void {
this._onClickHandler(this._selectionDataKeeper.getSelectedDataItem());
}
}
אחרי זה הייתי יוצר שני קלאסים:
1. הוא מנהל סוג של מידע (MenuItemsDataTypeButtonsHandler) שעושה:
1.א. מקבל את הDataItemType של עצמו.
1.ב. מממש את ה interface:
PHP:
export interface ISelectionDataItemKeeper {
getSelectedDataItem(): any;
}
1.ג. יודע
ליצור כפתורים (אסביר מאוחר יותר למה דווקא ליצור ולא מקבל אותם כפרמטר בctor) המתאימים לסוג המידע שלו (וכדאי לחלק את הכפתורים לפי התפריטים השונים) ולשמור אותם.
1.ד. יודע לקבל onSelectionChanged ולשמור את ה dataItem החדש (אסביר מאוחר יותר).
2. הוא מנהל כללי שיודע לעשות מספר דברים:
2.א. למלא את התפריט עם כפתורים.
2.ב. מקבל רשימה ב constructor של MenuItemsDataTypeButtonsHandler ושומר אותה.
2.ג. שיודע לקבל dataItem שנבחר (onSelectionChanged) ולמצוא את הMenuItemsDataTypeButtonsHandler הנכון מהרשימה שהוא שמר ולעדכן אותו (אות ג) שהשתנה פריט המידע. במידה והשתנה ה הMenuItemsDataTypeButtonsHandler מהבחירה הקודמת, הוא צריך לבנות את הכפתורים (שהוא מקבל מה buttonHandler).
י
וצא של design שלנו יש שלושה work flows:
א. טעינה (איך כל המידע נבנה בצורה נכונה שהכל יתחבר לאחר מכן בצורה טובה).
ב. המשתמש בחר פריט מידע אחר (onSelectionChanged) שבevent הזה אנחנו מצפים שיתעדכנו הכפתורים בהתאם לסוג של פריט המידע
ג. המשתמש לחץ על כפתור, אנחנו מצפים שכל כפתור יקבל את ה dataItem הרלוונטי ויוכל לטפל בו בעצמו, כך שמצד אחד יש לכל כפתור את כל המידע הרלוונטי לו אבל מצד שני הוא ה design מספיק גמיש בשביל לאפשר כל action שלא יהיה.
א. טעינה.
בתחילה, צריך לטעון buttonHandler (הקלאס הראשון בשמו המקוצר) עם הסוג שלו ולהוסיף את כל סוגי הכפתורים שצריכים להיות. כאשר הוא משמש כ factory (כלומר, הוא יוצר את הכפתורים על פי המיע שהוא מקבל כפרמטרים ולא מקבלים את הכפתורים כאובייקט מוגמר) בגלל שהכפתור יוכל לדעת מה פריט המידע שכרגע selected, הוא צריך לשמור את הbuttonHanlder שלו (שהוא למעשה שומר את האובייקט הבחור, למעלה ב1.ב אסביר בהמשך) ובשביל להמנע מבאגים, לא כדאי להעביר לכפתור את ה buttonHandler שלו ולאחר מכן להוסיף את הכפתור לרשימה של ה buttonHanlder (שהריי, יכול להיות שבטעות יקצו את הכפתור עם buttonHandler אחד ולאחר מכן יעבירו את הכפתור ל buttonHandler אחר).
לאחר שיש רשימה של buttonHandlers (שלכל אחד מהם יש את כל הכפתורים שלו), יוצרים מנהל כללי (קלאס 2) ושולחים לו את כל ה buttonHandlers.
ב. on selection changed
כאשר המשתמש בוחר פריט מידע, השרשרת הבאה של הevents קורה:
א. קופץ (מן הסתם) event בקומפוננטת האב שצריכה לקרוא למנהל הכללי (קלאס 2) עם פריט המידע החדש (2.ג.).
ב. המנהל הכללי מוצא את הbuttonHandler הנכון
ב.1. במידה והשתנה ה buttonHandler, בונה את הכפתורים בתפריט על פי הכפתורים של הbuttonHandler החדש.
ב.2. בכל אופן (כלומר, בין אם השתנה ה buttonHandler ובין אם לא), מעדכן את ה buttonHandler שהשתנה הdataItem.
ג. הbuttonHandler שומר את הפריט מידע הselected החדש.
ג. כאשר המשתמש לוחץ על כפתור (הפונקציה הזו כתובה כבר למעלה ב ButtonMetaData)
א. קופץ event בכפתור עצמו.
א.1. הכפתור מוצא את הdataItem שכרגע הוא selected (בעזרת קריאה ל buttonHandler שמממש את ה ISelectionDataItemKeeper).
א.2. הכפתור קורא לפונקציה handleOnClick שהוא קיבל ב ctor עם ה item שנבחר.
בהצלחה רבה, תשאלו חופשי