javascript - angular'da dinamik eklentiler
Soru, AngularJS'de başardığım benzer "şeyi" Angular 2+'da nasıl başarabileceğimizdir. "Şey"in ne olduğunu aşağıda açıklayacağım.
Soru açıklaması
Yani AngularJS'te oluşturduğum süreç şöyle tanımlanabilir:
- Bir sayfaya özel bir dinamik içerik eklemek istiyoruz, buna eklenti diyelim
- Bu içerik web istemcisinde tanımlı değildir, bunun yerine sunucudan yapılandırılmış bir biçimde alınmaktadır
Yani, eklentinin çalışması için gerekli olan html ve js dosyalarını sunucudan alıyoruz ve bunları sayfada yüklüyor ve gösteriyoruz. İstemci tarafında eklentinin gerekli mantığını tutmak için bir AngularJs direktifi oluşturuyorum.
İşte JavaScript eklenti kodu için örnek kod:
() => {
return {
templateUrl: 'directive-template-name',
restrict: "E",
controller: ['$scope', ... /* other dependecies */, function ($scope, ...) {
/* directive code */
}]
};
}
İşte eklenti yükleyici kodu için örnek kod:
// 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);
Görüldüğü gibi, bu yöntem geçerli bir JavaScript yüklemeye ve bunu bir AngularJS direktifine "derlemeye" ve ardından istediğiniz zaman sayfada görüntülemeye olanak tanır.
Angular 2+
Yeni Angular ile ilgili problem, anladığım kadarıyla, directive kavramının component kavramı ile değiştirilmiş olmasıdır. Ayrıca, tüm istemci tarafı kod artık typescript ile yazılıyor ve istemcinin tarayıcısı için javascript'e derleniyor. Anladığım kadarıyla, tüm bağımlılıklar derleme sürecinde çözülüyor.
Bu, bazı sorunlar yaratıyor ve Angular 2+ için dinamik eklentiler oluşturmayı engelliyor:
- Dinamik olarak oluşturulmuş bir bileşene bağımlılıkları nasıl enjekte edeceğimi bilmiyorum çünkü transpile işlemi gerçekleştiğinde tam olarak neye ihtiyacım olduğunu bilmiyorum.
- Diyelim ki birden fazla bileşenin aynı anda bir arada bulunmasını istiyorum (örneğin çocuk bileşenlere sahip bir ebeveyn dinamik bileşen) ve iletişim kurabilmelerini istiyorum, AngularJs durumunda bunu scope değişkeni kullanarak çözebilirdim. Angular 2+ bileşenleri izole olduğundan, bu sorunla nasıl başa çıkarım?
- Ayrıca, değerlendirilmiş JavaScript kodunda dinamik olarak oluşturulan bileşeni tutmak için ViewContainerRef'i nasıl oluşturabileceğini bilmiyorum. (Aşağıdaki kod örneklerine bakın)
Aşağıda şimdiye kadar aldığım kod örneklerini sağlayacağım. İçerik yükleyici TypeScript kodu:
//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);
}
}
Bu kod parçasında neler olup bittiğine referans olarak, bunu buradan aldım.
Eklenti örneği javascript kodu:
() => {
function dynamicMain() {
this.componentName = 'Dynamic Example Main';
}
return dynamicExampleMain;
}
Görülebileceği gibi, bu, kendisine herhangi bir hizmet veya diğer bileşenleri enjekte edemediği için onları kullanamayan oldukça basit bir dinamik eklentidir.
Beklenen cevap
Soruma bir yanıt olarak, Angular 2+ için dinamik eklentiler oluşturmaya çalışırken karşılaştığım sorunlara çözüm(ler) duymak isterim.
Angular 2+'de çalışırken dinamik eklentiler oluşturmanın daha iyi bir yolunu biliyorsanız (unutmayın: bunlar bir sunucudan alınır), bunu duymak da isterim.