Подтвердить что ты не робот

Angular: создание плагинов для сторонних пакетов (библиотек)

Я создал Angular Library (ngx-wig), и я хотел бы предоставить возможность расширения его функциональность с помощью плагинов.

Каким будет лучшее место для объявления плагина в Angular? (может быть что-то вроде myLibModule.forRoot(..)) и какой тип экземпляра должен быть сам плагин?

I решил одну и ту же проблему для AngularJs, просто добавив модуль для каждого плагина, в котором я регистрирую плагин, используя configProvider основного модуля. Не очень нравится это решение, потому что плагин регистрирует себя, но он должен отвечать за приложения, в которых используется библиотека.

UPDATE: связанная с этим проблема открывается в github здесь.

4b9b3361

Ответ 1

Я думаю, вы можете предоставить пользователям возможность использовать компонент в качестве подключаемого модуля. Этот компонент должен расширять вас абстрактным базовым компонентом плагина.

Например, 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 - глобальный токен angular, позволяющий динамически загружать плагины

2) Объявить NwClearStylesButtonComponent в массиве объявлений вашего модуля AppModule

3) Передайте его методу Ng2WigModule.forRoot

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

И тогда основной задачей будет динамическое создание вашего компонента с помощью ComponentFactoryResolver и ViewContainerRef (см. ng2wig-plugin.directive.ts в плунтере ниже)

Пример плунжера