javascript - תוספים דינמיים באנגלר
השאלה היא איך אפשר להשיג משהו דומה ב-Angular 2+ למה שהצלחתי לעשות ב-AngularJS. מה ה"דבר" הזה אני אתאר למטה.
תיאור השאלה
כך שהתהליך שיצרתי ב-AngularJS ניתן לתיאור כך:
- אנחנו רוצים להכניס תוכן דינמי מותאם אישית לדף, בואו נקרא לזה תוסף
- התוכן הזה לא מוגדר בקליינט האינטרנט, במקום זאת הוא נשלף משרת בצורה מובנית
כפי שאנו מקבלים מהשרת קבצי html ו-js הנדרשים כדי שהתוסף יפעל ואנו טוענים ומציגים אותם בעמוד. בצד הלקוח אני יוצר דירקטיבה של AngularJs כדי להכיל את הלוגיקה הנדרשת של התוסף.
הנה דוגמת הקוד עבור קוד תוסף של JavaScript:
() => {
return {
templateUrl: 'directive-template-name',
restrict: "E",
controller: ['$scope', ... /* other dependecies */, function ($scope, ...) {
/* directive code */
}]
};
}
הנה דוגמת הקוד עבור קוד טוען התוספים:
// evaluate js function and compile directive
var diretiveFactory = eval(content.jsFile);
// AngularJS CompileProvider
CompileProvider.directive.apply(null, [content.name, diretiveFactory]);
// append html code to element using angular
var wrapper = angular.element("#" + wrapperName);
wrapper.html(requestedDirective[0].htmlContent);
// initialize dynamic content
var wrapperScope = wrapper.scope();
this.$compile(wrapper)(wrapperScope);
כפי שניתן לראות, שיטה זו מאפשרת לטעון JavaScript תקף ול"לקמפל" אותו לתוך דיירקטיבה של AngularJS ואז להציג אותו בעמוד כרצון.
אנגולר 2+
הבעיה עם Angular החדש היא שהמושג של directive, ככל הנראה, הוחלף במושג של component. יתר על כן, כל הקוד בצד הלקוח נכתב עכשיו ב-TypeScript ומומר ל-JavaScript עבור הדפדפן של הלקוח. ככל שאני מבין, כל התלויות נפתרות בתהליך ההמרה.
זה יוצר כמה בעיות שמונעות יצירת פלאגינים דינמיים עבור Angular 2+:
- אני לא יודע איך להזריק תלותים לרכיב שנוצר דינמית כי אני לא יודע מה בדיוק אני צריך כאשר מתרחשת ההמרה.
- נניח שאני רוצה כמה רכיבים להתקיים במקביל (למשל רכיב דינמי הורה שמכיל רכיבי ילדים) ולהיות מסוגל לתקשר ביניהם, במקרה של AngularJs אני יכולתי לפתור בעיה זו באמצעות משתנה scope. במקרה של Angular 2+ הרכיבים מבודדים אז איך אני פותר בעיה זו.
- יתרה מכך, אני לא יודע איך אפשר ליצור ViewContainerRef כדי להחזיק את הרכיב שנוצר באופן דינמי בקוד Javascript מוערך. (ראו דוגמאות קוד למטה)
אני אספק דוגמאות קוד של מה שהגעתי עד כה למטה. קוד TypeScript של טעינת תוכן:
//some imports
import { Component, ComponentRef, Compiler, Injector, NgModule, NgModuleRef, ViewContainerRef} from '@angular/core';
// plugin content structure
class DynamicPageModel {
name: string;
htmlFile: string;
jsFile: string;
}
export class DynamicContentService {
constructor(
private _compiler: Compiler,
private _injector: Injector,
private _m: NgModuleRef<any>
) { }
public LoadDynamicContent(container: ViewContainerRef, content: DynamicPageModel) {
// evaluate js function and compile component
var tmpCmp = Component({
template: content.htmlFile,
selector: content.name
})(eval(content.jsFile)());
var tmpModule = NgModule({declarations: [tmpCmp as any]})(class { });
var factories = this._compiler.compileModuleAndAllComponentsSync(tmpModule)
var f = factories.componentFactories[0];
var cmpRef = f.create(this._injector, [], null, this._m);
// insert component into the container
container.insert(cmpRef.hostView);
}
}
לצורך התייחסות למה שקורה בקוד הזה, קיבלתי אותו מכאן.
דוגמת קוד JavaScript לתוסף:
() => {
function dynamicMain() {
this.componentName = 'Dynamic Example Main';
}
return dynamicExampleMain;
}
כפי שאפשר לראות, זהו תוסף דינמי פשוט למדי שאינו מסוגל להשתמש בשום שירותים או רכיבים אחרים מכיוון שאינו מסוגל להזריק אותם לתוכו עצמו.
תשובה צפויה
כתשובה לשאלתי, אני רוצה לשמוע פתרון(ות) לבעיות שנתקלתי בהן כאשר ניסיתי ליצור תוספים דינמיים עבור Angular 2+.
אם אתה יודע גישה טובה יותר ליצירת פלאגינים דינמיים (זכור: הם נאספים משרת) בזמן ריצה ב-Angular 2+, אני גם אשמח לשמוע עליה.