2017-02-13 12 views
0

Я хочу абстрагировать компонент Tree в моем проекте, конкретно JSTree. Поэтому я написал интерфейс и адаптер для JSTree, который реализует этот интерфейс. Я использую Injection Dependency из-за модульного тестирования.Angular - Dependency Inject объект/класс с конструктором, который имеет параметры

  1. Для построения дерева (jstree) необходим идентификатор DOM и данные JSON, необходимые для построения дерева.
  2. Данные извлекаются с сервера, что означает, что адаптер должен быть подходящим для конструктора, который должен построить три с данными.
  3. Проблема в том, когда я создаю конструктор, который я не могу использовать (я могу ввести местозаполнитель/идентификатор, но не данные из службы)

Классы видны на диаграмме классов (небольшая ошибка подключения между TreeService и провайдером должна быть агрегацией):

enter image description here

Проблема заключается в том, что TreeService должен извлекать данные с сервера, чтобы поставщик передал его конструктору JSTreeComponents для его создания. Это означает, что JsTreeComponent больше не может быть @Injectable(), который ограничивает тестируемость класса.

Вопросы:

  1. Должна ли TreeService построить/впрыскивать JsTreeComponent или если TreeComponent сделать это или событие Продлить его в качестве базового класса
  2. Как решить, что JsTreeComponent является инъекционным в угловой/Машинописи altrought конструктор должен вызываться с данными сервера (. пожалуйста не предлагают сделать это метод, как tree.loadData (JSON))

Возможный способ его создания внутри TreeService - Пример в angular2/машинопись но может быть angularjs тоже:

@Injectable() 
    export class TreeService { 

     chapters: any; 
     treeHandler: ITreeComponent; 
     readonly placeholder: string = 'tree-placeholder'; 

     constructor(private treeProvider: TreeProvider, 
      @Inject(new JsTreeComponent(this.placeholder, ????data??)) tree: ITreeComponent) { } 

     initializeTree(placeholder: string): Observable<Response> { 
      let provider = this.treeProvider.getNodes(); 
      provider.subscribe(
       (data: any) => { 
        this.treeHandler = <ITreeComponent>(new JsTreeComponent(placeholder, data)); 
       } 
      ); 
      return provider; 
     } 
    } 

Два способа показаны первый, чтобы создать его с «новым», но проблема в том, проверяемость. Второй заключается в том, чтобы вводить его, но проблема в том, что я не могу передать данные, загруженные из провайдера, чтобы построить дерево, и я не хочу использовать такую ​​функцию, как .loadData (json) - он должен подумать о конструкторе.

Я мог бы также использовать Singletone, чтобы заставить JsTreeComponent быть построен с данными, но «обойти» Конструктор

+0

почему косяк у передать данные из переменного класса –

+0

инъекционного компонент к службе, как правило, не имеет смысла в Angular2.Мне непонятно, что вы пытаетесь выполнить. Почему вы хотите это сделать? –

+0

Я мог бы также ввести его или расширить его в компоненте/контроллере. Только расширение решает проблему с Injection, но все же у меня проблема, как заставить передачу параметра данных в конструктор, я имею в виду, что я мог бы сделать это через super в конструкторе Components. – teter

ответ

0

Одно из решений с использованием синглтона, но я не думаю, что это оптимально. Теперь Адаптер инъектируется, поэтому его можно легко высмеять в тесте и изолировать от углов TreeComponent (я могу легко заменить jstree другим компонентом или перенести обертку между угловыми и угловыми при использовании машинописного текста).


@Injectable() 
export class JsTreeAdapter implements TreeInterface { 

    private static _instance: JsTreeComponent; 

    public constructor() { 
     throw new Error("Error: Instantiation failed: Use JsTreeComponent.getInstance() instead of new."); 
    } 

    public static getInstance(placeholder: string, data: any): JsTreeComponent { 
     if (this._instance) 
      return this._instance; 
     else { 
      this._instance = new this(); 
      this._instance.constructTree(placeholder, data); 
      return this._instance; 
     } 
    } 
} 

и в конструкторе инъекция:

@Component({}) 
export class TreeComponent { 

    readonly placeholder: string = 'tree-placeholder'; 
    treeHandler : TreeInterface; 

    constructor(private treeService: ChapterTreeService, private treeHandler: JsTreeAdapter) { 
     this.treeService.getNodes().subscribe((data: any) => { 
      this.treeHandler = ChapterJsTree.getInstance(this.placeholder, data); 
     }); 
    } 
} 
+0

this.treeHandler = ChapterJsTree.getInstance (this.placeholder, data); Я думаю, что это действительно уродливо, но я не уверен, нужно ли мне повторно ссылаться на него, вероятно, да – teter