Angular:为第三方软件包(库)创建插件

时间:2017-06-20 13:31:44

标签: javascript angular angular-module angular-library

我创建了 Angular Library ngx-wig),我希望能够通过插件扩展其功能。

在Angular中声明插件的最佳位置是什么? (可能类似于myLibModule.forRoot(..) )和插件本身应该是什么类型的实例?

AngularJs solved same issue只是为每个插件添加模块,我使用主模块configProvider注册插件。不太喜欢这个解决方案,因为插件会自行注册,但它应该是使用库的应用程序的责任。

更新:在github here上打开了相关问题。

1 个答案:

答案 0 :(得分:2)

我认为您可以为用户提供使用组件作为插件。该组件必须扩展您的抽象基本插件组件。

例如clear-styles插件可能看起来像

@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插件

@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();
  }
}

其中Ng2WigPluginComponent是您的库提供的抽象基类:

export abstract class Ng2WigPluginComponent {
  execCommand: Function;
  editMode: boolean;
  content: string;

  editModelChange: EventEmitter<boolean> = new EventEmitter();
  contentChange: EventEmitter<string> = new EventEmitter();
}

因此用户可以轻松地在基类属性中使用声明。

要注册此类插件,我们可以使用forRoot方法提及的方法。为此你需要

1)为您配置库模块,如下所示:

<强> 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},
      ]
    };
  }
}

其中

  • NG_WIG_CUSTOM_BUTTONS是您的全局库令牌,用于识别库中提供的插件

<强> 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是角度全局令牌,可以动态加载插件

2)NwClearStylesButtonComponent模块的声明数组中声明AppModule

3)将其传递给Ng2WigModule.forRoot方法

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

然后主要的任务是使用ComponentFactoryResolverViewContainerRef动态生成您的组件(请参阅下面的ng2wig-plugin.directive.ts

<强> Plunker Example