Пользовательский сервис Angular 2 не введен в директиву

У меня есть app.component вроде этого.

import {Component} from "angular2/core"
import {HTTP_PROVIDERS} from "angular2/http"

import {ChartDataService} from '../service/chartData.service'
import {FilterService} from "../service/filter.service"

@Component({
    selector: 'app',
    template: `
        <sidebar (filterChange)="onFilterChange($event)"></sidebar>
        <div dsChart></div>
    `,
    directives: [SidebarComponent, ChartDirective],
    providers: [HTTP_PROVIDERS, FilterService, ChartDataService],
    styleUrls: ['app/main/app.component.css']
})

export class AppComponent {
     //some more code
}

chartData.service.ts:

import {Injectable} from 'angular2/core'
import {Http, Response, Headers, RequestOptions, RequestMethod} from 'angular2/http'

import {Url} from '../url'
import {FilterModel} from '../model/filter.model'
import {INode} from "../model/node.model"

@Injectable()
export class ChartDataService {
    constructor(private _http: Http) {
        this._headers.append('Content-Type', 'application/json');
    }    

    getData(model?: FilterModel) {
    }
}

Затем я пытаюсь использовать ChartDataService внутри chart.directive, который является дочерним компонентом для app.component. chart.directive.ts:

import {Directive, ElementRef, Input, OnInit} from 'angular2/core'
import {ChartDataService} from "../service/chartdata.service"

@Directive({
    selector: '[dsChart]'
})
export class ChartDirective implements OnInit {    
    constructor(
        private el: ElementRef,
        private _dataService: ChartDataService) {
    }

    ngOnInit() {
        this._dataService.getData()
            .then(node => this._render(node))
            .catch(error => { throw error });
    }

    private _render(root: INode) {}
}

Но это не удается. Через документы каждый компонент имеет инжектор, который создает зависимости на уровне компонента. Если нет подходящих провайдеров уровня компонента, используется провайдер родительского компонента. Это прекрасно работает для классов с декоратором @Component(). Добавление providers: [ChartDataService] к объявлению @Directive помогает, но это означает, что каждый декоратор будет иметь отдельный экземпляр ChartDataService, что нежелательно.

Любые идеи? Или это по дизайну?


person forik    schedule 04.03.2016    source источник


Ответы (2)


Это может быть проблема с порядком импорта... Если в app.component.ts вы импортируете ChartDirective до ChartDataService, вы можете получить упомянутую вами ошибку:

Нет провайдера для ChartDataService! (Директива диаграммы -> Служба данных диаграммы)

Вы должны импортировать сервисы, которые используют дочерние компоненты/директивы, перед импортом самого компонента:

// no error
import {ChartDataService} from '../service/chartData.service'
import {ChartDirective} from '../chart.directive'

// can cause an error
import {ChartDirective} from '../chart.directive'
import {ChartDataService} from '../service/chartData.service'

Мне не удалось воспроизвести эту проблему здесь: http://plnkr.co/edit/NoZJnCMlqKkOMm5erfDW, но Я могу подтвердить, что это может произойти:

// routes.ts
// no error
export {SettingsRoute} from './routes/settings/settings.route'
export {RootRoute} from './routes/root/root.route'

// this causes error
// export {RootRoute} from './routes/root/root.route'
// export {SettingsRoute} from './routes/settings/settings.route'

// root.route.ts
import {SettingsRoute} from './routes'
@RouteConfig([
  { path: '/settings/...', name: 'Settings', component: SettingsRoute },
])
export class RootRoute {...}

Ошибка Нет ошибок

person Sasxa    schedule 05.03.2016
comment
Никаких изменений для меня после переупорядочения импорта. - person forik; 08.03.2016

Я забыл упомянуть, что использовал бета-версию 7. После обновления до beta.8 проблема исчезла.

person forik    schedule 04.03.2016
comment
Хорошо, потому что я понятия не имел, почему это не работает для тебя. - person Mark Rajcok; 05.03.2016