সম্পাদনা - ২.৩.০ সম্পর্কিত (২০১-12-১২-০7)
দ্রষ্টব্য: পূর্ববর্তী সংস্করণে সমাধান পেতে, এই পোস্টের ইতিহাসটি পরীক্ষা করুন
অনুরূপ বিষয়টি এখানে কৌণিক 2 এ ile সংকলনের সমতুল্য আলোচনা করা হয় । আমাদের ব্যবহার করা দরকার JitCompiler
এবং NgModule
। NgModule
এখানে Angular2 এ সম্পর্কে আরও পড়ুন :
সংক্ষেপে
এখানে একটি কার্যকারী প্লঙ্কার / উদাহরণ রয়েছে (ডায়নামিক টেম্পলেট, ডায়নামিক উপাদান ধরণ, গতিশীল মডিউল JitCompiler
, ... ক্রিয়ায়)
প্রধান হল:
1) তৈরি টেমপ্লেট
2) এটি ComponentFactory
ক্যাশের মধ্যে - এ যান 7)
3) - তৈরি Component
4) - তৈরি Module
5) - কম্পাইল Module
6) - প্রত্যাবর্তন (এবং পরে ব্যবহার করার জন্য ক্যাশে) ComponentFactory
7) ব্যবহার উদ্দিষ্ট এবং ComponentFactory
একটি দৃষ্টান্ত তৈরি করতে গতিশীলComponent
এখানে একটি কোড স্নিপেট (এটির আরও এখানে ) - আমাদের কাস্টম বিল্ডার কেবল নির্মিত / ক্যাশে ফিরে আসছেন ComponentFactory
এবং টার্গেটের স্থানধারক এর উদাহরণ তৈরির জন্য ব্যবহার করেDynamicComponent
// here we get a TEMPLATE with dynamic content === TODO
var template = this.templateBuilder.prepareTemplate(this.entity, useTextarea);
// here we get Factory (just compiled or from cache)
this.typeBuilder
.createComponentFactory(template)
.then((factory: ComponentFactory<IHaveDynamicData>) =>
{
// Target will instantiate and inject component (we'll keep reference to it)
this.componentRef = this
.dynamicComponentTarget
.createComponent(factory);
// let's inject @Inputs to component instance
let component = this.componentRef.instance;
component.entity = this.entity;
//...
});
এটি এটি - সংক্ষেপে এটি। আরও বিশদ পেতে .. নীচে পড়ুন
।
টি এল & ডিআর
কোনও প্লাঙ্কার পর্যবেক্ষণ করুন এবং কিছু স্নিপেটের আরও ব্যাখ্যা প্রয়োজন হলে বিশদটি পড়তে ফিরে আসুন
।
বিশদ ব্যাখ্যা - Angular2 RC6 ++ & রানটাইম উপাদান components
এই দৃশ্যের বর্ণনার নীচে , আমরা করব
- একটি মডিউল তৈরি করুন
PartsModule:NgModule
(ছোট টুকরো ধারক)
- অন্য একটি মডিউল তৈরি করুন
DynamicModule:NgModule
, যাতে আমাদের গতিশীল উপাদান থাকবে (এবং PartsModule
গতিশীলভাবে উল্লেখ )
- গতিশীল টেম্পলেট তৈরি করুন (সহজ পদ্ধতির)
- নতুন
Component
ধরণের তৈরি করুন (কেবলমাত্র টেমপ্লেট পরিবর্তিত হলে)
- নতুন তৈরি
RuntimeModule:NgModule
। এই মডিউলটিতে পূর্বে নির্মিত Component
প্রকার থাকবে
JitCompiler.compileModuleAndAllComponentsAsync(runtimeModule)
পেতে কলComponentFactory
DynamicComponent
লক্ষ্য লক্ষ্য স্থানধারক এবং - এর চাকরির একটি দৃষ্টান্ত তৈরি করুনComponentFactory
- দায়িত্ব অর্পণ
@Inputs
করার নতুন উদাহরণ (থেকে সুইচ INPUT
করার TEXTAREA
এডিটিং) , গ্রাস@Outputs
NgModule
আমাদের একটি NgModule
এস দরকার
যদিও আমি খুব সাধারণ উদাহরণটি দেখাতে চাই, এই ক্ষেত্রে আমার তিনটি মডিউল লাগবে (আসলে 4 - তবে আমি অ্যাপমোডুল গণনা করি না) । দয়া করে সত্যিকারের শক্ত গতিশীল উপাদান জেনারেটরের ভিত্তি হিসাবে সাধারণ স্নিপেটের চেয়ে এটি নিন ।
সমস্ত ছোট উপাদানগুলির জন্য একটি মডিউল থাকবে , যেমন string-editor
, text-editor
( date-editor
, number-editor
...)
@NgModule({
imports: [
CommonModule,
FormsModule
],
declarations: [
DYNAMIC_DIRECTIVES
],
exports: [
DYNAMIC_DIRECTIVES,
CommonModule,
FormsModule
]
})
export class PartsModule { }
যেখানে DYNAMIC_DIRECTIVES
এক্সটেনসেবল এবং এটি আমাদের গতিশীল উপাদান টেম্পলেট / প্রকারের জন্য ব্যবহৃত সমস্ত ছোট ছোট অংশগুলি ধারণ করার উদ্দেশ্যে। অ্যাপ / পার্টস / পার্টস.মডিউল.টগুলি পরীক্ষা করুন
দ্বিতীয়টি আমাদের গতিশীল স্টাফ হ্যান্ডলিংয়ের জন্য মডিউল হবে। এটিতে হোস্টিং উপাদান এবং কিছু সরবরাহকারী থাকবে .. যা একক হবে। এর জন্য আমরা তাদের স্ট্যান্ডার্ড পদ্ধতিতে প্রকাশ করব withforRoot()
import { DynamicDetail } from './detail.view';
import { DynamicTypeBuilder } from './type.builder';
import { DynamicTemplateBuilder } from './template.builder';
@NgModule({
imports: [ PartsModule ],
declarations: [ DynamicDetail ],
exports: [ DynamicDetail],
})
export class DynamicModule {
static forRoot()
{
return {
ngModule: DynamicModule,
providers: [ // singletons accross the whole app
DynamicTemplateBuilder,
DynamicTypeBuilder
],
};
}
}
এর ব্যবহারটি পরীক্ষা forRoot()
করুনAppModule
অবশেষে, আমাদের অ্যাডহক, রানটাইম মডিউল প্রয়োজন হবে .. তবে এটি পরে তৈরি করা হবে, DynamicTypeBuilder
কাজের অংশ হিসাবে ।
সামনে মডিউল, অ্যাপ্লিকেশন মডিউল, হ'ল সংকলক সরবরাহকারী ঘোষণা করে:
...
import { COMPILER_PROVIDERS } from '@angular/compiler';
import { AppComponent } from './app.component';
import { DynamicModule } from './dynamic/dynamic.module';
@NgModule({
imports: [
BrowserModule,
DynamicModule.forRoot() // singletons
],
declarations: [ AppComponent],
providers: [
COMPILER_PROVIDERS // this is an app singleton declaration
],
এনজিডমডুল সম্পর্কে আরও পড়ুন (পড়ুন) সেখানে:
একটি টেম্পলেট নির্মাতা
আমাদের উদাহরণে আমরা এই ধরণের সত্তাটির বিশদ প্রক্রিয়া করব
entity = {
code: "ABC123",
description: "A description of this Entity"
};
একটি তৈরি করতে template
, এই নিমজ্জনকারীটিতে আমরা এই সাধারণ / নিষ্পাপ নির্মাতা ব্যবহার করি।
আসল সমাধান, একটি প্রকৃত টেম্পলেট নির্মাতা, সেই জায়গা যেখানে আপনার অ্যাপ্লিকেশন অনেক কিছু করতে পারে
// plunker - app/dynamic/template.builder.ts
import {Injectable} from "@angular/core";
@Injectable()
export class DynamicTemplateBuilder {
public prepareTemplate(entity: any, useTextarea: boolean){
let properties = Object.keys(entity);
let template = "<form >";
let editorName = useTextarea
? "text-editor"
: "string-editor";
properties.forEach((propertyName) =>{
template += `
<${editorName}
[propertyName]="'${propertyName}'"
[entity]="entity"
></${editorName}>`;
});
return template + "</form>";
}
}
এখানে একটি কৌশলটি - এটি একটি টেম্পলেট তৈরি করে যা পরিচিত বৈশিষ্ট্যের কিছু সেট ব্যবহার করে, যেমন entity
। এই জাতীয় সম্পত্তি (-ies) অবশ্যই গতিশীল উপাদানগুলির অংশ হতে হবে, যা আমরা পরবর্তী তৈরি করব।
এটিকে কিছুটা আরও সহজ করার জন্য, আমরা বৈশিষ্ট্যগুলি সংজ্ঞায়িত করতে একটি ইন্টারফেস ব্যবহার করতে পারি, যা আমাদের টেমপ্লেট নির্মাতা ব্যবহার করতে পারেন। এটি আমাদের গতিশীল উপাদান ধরণের দ্বারা প্রয়োগ করা হবে।
export interface IHaveDynamicData {
public entity: any;
...
}
একজন ComponentFactory
নির্মাতা
এখানে খুব গুরুত্বপূর্ণ জিনিসটি মনে রাখা:
আমাদের উপাদানগুলির ধরণ, আমাদের সাথে বিল্ড করা DynamicTypeBuilder
পৃথক হতে পারে - তবে কেবল এটির টেমপ্লেট (উপরে তৈরি) দ্বারা । উপাদানগুলির বৈশিষ্ট্য (ইনপুট, আউটপুট বা কিছু সুরক্ষিত) এখনও একই। আমাদের যদি বিভিন্ন বৈশিষ্ট্যের প্রয়োজন হয় তবে আমাদের টেমপ্লেট এবং প্রকারের নির্মাতার বিভিন্ন সংমিশ্রণটি সংজ্ঞায়িত করা উচিত
সুতরাং, আমরা আমাদের সমাধানের মূলটি স্পর্শ করছি। বিল্ডার, 1) তৈরি করবেন ComponentType
2) এটি তৈরি করুন NgModule
3) সংকলন ComponentFactory
4) এটি পুনরায় ব্যবহারের জন্য ক্যাশে করুন ।
আমাদের যে নির্ভরতা অর্জন করতে হবে:
// plunker - app/dynamic/type.builder.ts
import { JitCompiler } from '@angular/compiler';
@Injectable()
export class DynamicTypeBuilder {
// wee need Dynamic component builder
constructor(
protected compiler: JitCompiler
) {}
এবং কীভাবে পাবেন তা এখানে একটি স্নিপেট রয়েছে ComponentFactory
:
// plunker - app/dynamic/type.builder.ts
// this object is singleton - so we can use this as a cache
private _cacheOfFactories:
{[templateKey: string]: ComponentFactory<IHaveDynamicData>} = {};
public createComponentFactory(template: string)
: Promise<ComponentFactory<IHaveDynamicData>> {
let factory = this._cacheOfFactories[template];
if (factory) {
console.log("Module and Type are returned from cache")
return new Promise((resolve) => {
resolve(factory);
});
}
// unknown template ... let's create a Type for it
let type = this.createNewComponent(template);
let module = this.createComponentModule(type);
return new Promise((resolve) => {
this.compiler
.compileModuleAndAllComponentsAsync(module)
.then((moduleWithFactories) =>
{
factory = _.find(moduleWithFactories.componentFactories
, { componentType: type });
this._cacheOfFactories[template] = factory;
resolve(factory);
});
});
}
উপরে আমরা উভয় এবং তৈরি এবং ক্যাশে করি । কারণ যদি টেমপ্লেট (প্রকৃতপক্ষে সেই সমস্তের প্রকৃত গতিশীল অংশ) একই হয় তবে আমরা পুনরায় ব্যবহার করতে পারিComponent
Module
এবং এখানে দুটি পদ্ধতি রয়েছে যা রানটাইমের সময় সজ্জিত শ্রেণি / প্রকারগুলি কীভাবে তৈরি করা যায় তা দুর্দান্ত উপস্থাপন করে । শুধু @Component
বরং@NgModule
protected createNewComponent (tmpl:string) {
@Component({
selector: 'dynamic-component',
template: tmpl,
})
class CustomDynamicComponent implements IHaveDynamicData {
@Input() public entity: any;
};
// a component for this particular template
return CustomDynamicComponent;
}
protected createComponentModule (componentType: any) {
@NgModule({
imports: [
PartsModule, // there are 'text-editor', 'string-editor'...
],
declarations: [
componentType
],
})
class RuntimeComponentModule
{
}
// a module for just this Type
return RuntimeComponentModule;
}
গুরুত্বপূর্ণ:
আমাদের উপাদান গতিশীল প্রকারভেদ পৃথক, কিন্তু কেবল টেমপ্লেট দ্বারা। সুতরাং আমরা সেগুলি তাদের ক্যাশে করতে ব্যবহার করি। এটি সত্যিই খুব গুরুত্বপূর্ণ। Angular2 এগুলিকেও ক্যাশে করবে .. টাইপ করে । এবং যদি আমরা একই ধরণের টেমপ্লেটগুলিকে নতুন ধরণের জন্য পুনরায় তৈরি করি ... আমরা মেমরি ফাঁস উত্পন্ন করা শুরু করব।
ComponentFactory
হোস্টিং উপাদান দ্বারা ব্যবহৃত
ফাইনাল পিস একটি উপাদান যা আমাদের গতিশীল উপাদানগুলির জন্য লক্ষ্য হোস্ট করে <div #dynamicContentPlaceHolder></div>
। আমরা এটিতে একটি রেফারেন্স পাই এবং ComponentFactory
একটি উপাদান তৈরি করতে ব্যবহার করি । এটি সংক্ষেপে, এবং এখানে component উপাদানগুলির সমস্ত টুকরা এখানে রয়েছে (যদি প্রয়োজন হয় তবে এখানে খোলার চূড়ান্ত )
প্রথমে আমদানি বিবৃতিগুলির সংক্ষিপ্তসার করা যাক:
import {Component, ComponentRef,ViewChild,ViewContainerRef} from '@angular/core';
import {AfterViewInit,OnInit,OnDestroy,OnChanges,SimpleChange} from '@angular/core';
import { IHaveDynamicData, DynamicTypeBuilder } from './type.builder';
import { DynamicTemplateBuilder } from './template.builder';
@Component({
selector: 'dynamic-detail',
template: `
<div>
check/uncheck to use INPUT vs TEXTAREA:
<input type="checkbox" #val (click)="refreshContent(val.checked)" /><hr />
<div #dynamicContentPlaceHolder></div> <hr />
entity: <pre>{{entity | json}}</pre>
</div>
`,
})
export class DynamicDetail implements AfterViewInit, OnChanges, OnDestroy, OnInit
{
// wee need Dynamic component builder
constructor(
protected typeBuilder: DynamicTypeBuilder,
protected templateBuilder: DynamicTemplateBuilder
) {}
...
আমরা কেবলমাত্র টেমপ্লেট এবং উপাদান বিল্ডারগুলি গ্রহণ করি। এরপরে এমন বৈশিষ্ট্য রয়েছে যা আমাদের উদাহরণের জন্য প্রয়োজনীয় (মন্তব্যগুলিতে আরও)
// reference for a <div> with #dynamicContentPlaceHolder
@ViewChild('dynamicContentPlaceHolder', {read: ViewContainerRef})
protected dynamicComponentTarget: ViewContainerRef;
// this will be reference to dynamic content - to be able to destroy it
protected componentRef: ComponentRef<IHaveDynamicData>;
// until ngAfterViewInit, we cannot start (firstly) to process dynamic stuff
protected wasViewInitialized = false;
// example entity ... to be recieved from other app parts
// this is kind of candiate for @Input
protected entity = {
code: "ABC123",
description: "A description of this Entity"
};
এই সাধারণ দৃশ্যে, আমাদের হোস্টিং উপাদানটির কোনও নেই @Input
। সুতরাং এটি পরিবর্তন সম্পর্কে প্রতিক্রিয়া জানাতে হবে না। তবে এই সত্যটি থাকা সত্ত্বেও (এবং আগত পরিবর্তনগুলির জন্য প্রস্তুত থাকতে হবে) - উপাদানটি ইতিমধ্যে (প্রথম দিকে) শুরু করা থাকলে আমাদের কিছু পতাকা প্রবর্তন করতে হবে। এবং কেবল তখনই আমরা যাদুটি শুরু করতে পারি।
শেষ পর্যন্ত আমরা আমাদের উপাদান নির্মাতাকে ব্যবহার করব এবং এটি স্রেফ সংকলিত / ক্যাশেড করব ComponentFacotry
। আমাদের লক্ষ্য স্থানধারক instantiate করতে বলা হবে যে কারখানা সঙ্গে।Component
protected refreshContent(useTextarea: boolean = false){
if (this.componentRef) {
this.componentRef.destroy();
}
// here we get a TEMPLATE with dynamic content === TODO
var template = this.templateBuilder.prepareTemplate(this.entity, useTextarea);
// here we get Factory (just compiled or from cache)
this.typeBuilder
.createComponentFactory(template)
.then((factory: ComponentFactory<IHaveDynamicData>) =>
{
// Target will instantiate and inject component (we'll keep reference to it)
this.componentRef = this
.dynamicComponentTarget
.createComponent(factory);
// let's inject @Inputs to component instance
let component = this.componentRef.instance;
component.entity = this.entity;
//...
});
}
ছোট এক্সটেনশন
এছাড়াও, আমাদের সঙ্কলিত টেম্পলেটগুলির একটি রেফারেন্স রাখা দরকার .. destroy()
এটি যথাযথভাবে সক্ষম হতে , যখনই আমরা এটি পরিবর্তন করব।
// this is the best moment where to start to process dynamic stuff
public ngAfterViewInit(): void
{
this.wasViewInitialized = true;
this.refreshContent();
}
// wasViewInitialized is an IMPORTANT switch
// when this component would have its own changing @Input()
// - then we have to wait till view is intialized - first OnChange is too soon
public ngOnChanges(changes: {[key: string]: SimpleChange}): void
{
if (this.wasViewInitialized) {
return;
}
this.refreshContent();
}
public ngOnDestroy(){
if (this.componentRef) {
this.componentRef.destroy();
this.componentRef = null;
}
}
সম্পন্ন
এটা প্রায় কাছাকাছি। ডায়নামিকভাবে যা কিছু নির্মিত হয়েছিল তা ধ্বংস করতে ভুলবেন না (ngOnDestroy) । এছাড়াও, গতিশীল ক্যাশে নিশ্চিত হন types
এবং modules
কেবলমাত্র পার্থক্য যদি তাদের টেম্পলেট হয়।
এখানে সমস্ত কর্মে এটি পরীক্ষা করে দেখুন
এই পোস্টটির পূর্ববর্তী সংস্করণগুলি (যেমন আরসি 5 সম্পর্কিত) দেখতে ইতিহাসটি পরীক্ষা করুন