Angular: Creating plugins for 3rd party packages (libraries)

匿名 (未验证) 提交于 2019-12-03 02:50:02

问题:

I created Angular Library (ngx-wig) and I would like to provide an ability to extend its functionality by using plugins.

What would be the best place to declare plugin in Angular? (may be something like myLibModule.forRoot(..)) and what type of instance should be plugin itself?

I solved same issue for AngularJs just by adding module for each plugin in which I register plugin by using configProvider of main module. Don't really like this solution because plugin registers itself, but it should be responsibility of applications where library is used.

UPDATE: related issue is opened on github here.

回答1:

I think you can provide users to use component as a plug-in. This component has to extends you abstract base plugin component.

For example clear-styles plugin could look like

@Component({   selector: `nw-clear-styles-button`,   template: `     <button (click)="clearStyles($event)"          [disabled]="editMode || disabled"          class="nw-button clear-styles" title="Clear Styles">       Clear Styles     </button>` }) export class NwClearStylesButtonComponent extends Ng2WigPluginComponent {   constructor() {     super();   }    clearStyles() {     const div = document.createElement('div');     div.innerHTML = this.content;     this.contentChange.emit(div.textContent);   } } 

format plugin

@Component({   selector: `nw-formats-button`,   template: `     <select class="nw-select"             [(ngModel)]="format"             (ngModelChange)="execCommand('formatblock', format.value)"             [disabled]="editMode || disabled">       <option *ngFor="let format of formats" [ngValue]="format">{{ format.name }}</option>     </select>   ` }) export class NwFormatButtonComponent extends Ng2WigPluginComponent {   formats = [     {name: 'Normal text', value: '<p>'},     {name: 'Header 1', value: '<h1>'},     {name: 'Header 2', value: '<h2>'},     {name: 'Header 3', value: '<h3>'}   ];    format = this.formats[0];    constructor() {     super();   } } 

where Ng2WigPluginComponent is abstract base class provided by your library:

export abstract class Ng2WigPluginComponent {   execCommand: Function;   editMode: boolean;   content: string;    editModelChange: EventEmitter<boolean> = new EventEmitter();   contentChange: EventEmitter<string> = new EventEmitter(); } 

So users can easily use declared in base class properties.

To register such plugins we can use mentioned by you forRoot method. For that you need to

1) configure you library module like follows:

ng2wig.module.ts

@NgModule({  ... }) export class Ng2WigModule {   static forRoot(entryComponents: CustomButton[]) {     return {       ngModule: Ng2WigModule,       providers: [         Ng2WigToolbarService,         {provide: NG_WIG_CUSTOM_BUTTONS, useValue: entryComponents},         {provide: ANALYZE_FOR_ENTRY_COMPONENTS, multi: true, useValue: entryComponents},       ]     };   } } 

where

  • NG_WIG_CUSTOM_BUTTONS is your global library token to recognize provided plugins inside library

ng2wig-toolbar.service.ts

@Injectable() export class Ng2WigToolbarService {   constructor(@Optional() @Inject(NG_WIG_CUSTOM_BUTTONS) customButtons: CustomButton[]) {     if (customButtons) {       customButtons.forEach(plugin => this.addCustomButton(plugin.pluginName, plugin.component));     }   } 
  • ANALYZE_FOR_ENTRY_COMPONENTS is angular global token to be able to load plugins dynamically

2) Declare NwClearStylesButtonComponent in declarations array of your AppModule module

3) Pass it to the Ng2WigModule.forRoot method

Ng2WigModule.forRoot([    { pluginName: 'clear-styles', component: NwClearStylesButtonComponent },    { pluginName: 'format', component: NwFormatButtonComponent } ])  

And then main you task will be to dynamically generate your component by using ComponentFactoryResolver and ViewContainerRef (see ng2wig-plugin.directive.ts in plunker below)

Plunker Example



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!