2017-02-22 38 views
8

У меня есть компонент, объявляющий службу MetricsService. Для этой службы требуется как http-модуль плюс две строки, определяющие хост, так и используемый ключ.Как написать конструктор службы, который требует параметров в угловом 2?

Служба метрик выглядит следующим образом:

@Injectable() 
export class MetricsService { 
    constructor(
     private http: Http, 
     public wsAuthKey: string, 
     public wsHost: string 
     ) { 
     this.wsAuthKey = wsAuthKey || "blahblahblahblahblahblahblahblah="; 
     this.wsHost  = wsHost || "https://preprod-admin.myservice.ws"; 
    } 

Компонент, который использует это записывается следующим образом:

export class DatavizComponent implements OnInit, OnChanges { 
    constructor(
     private zms: MetricsService, 
    ) { 
    } 

Мой вопрос, как я должен написать компонент конструктор так, что все это работает, в том числе передача хоста и ключа (но не передача http)?

Примечание: код в данный момент не компилируется.

Чтобы быть более точным, я ожидаю, что компонент в условии то данных приложения-зависимости, как это:

export class DatavizComponent implements OnInit, OnChanges { 
     constructor(
      private zms = MetricsService("http://myhost.com", "mykey"), 
     ) { 
     } 

Но если это работает, как передать HTTP?

ОБНОВЛЕНИЯ ПОСЛЕ Предложенное решение:

export class MetricsService { 

    constructor(
     private http: Http, 
     @Inject('wsAuthKey') @Optional() public wsAuthKey?: string, 
     @Inject('wsHost') @Optional() public wsHost?: string 
     ) { 
     this.wsAuthKey = wsAuthKey || "blahblah="; 
     this.wsHost  = wsHost || "https://preprod-admin.host.ws"; 


     console.log("MetricsService constructor=" 
      + " wsAuthKey="+this.wsAuthKey 
      + ", wsHost="+this.wsHost 
     ); 

    } 

В компоненте:

@Component({ 
    selector: 'dataviz-offers-volumes', 
    templateUrl: 'app/dataviz.component.html', 
    styleUrls: ['app/dataviz.component.css'], 
    encapsulation: ViewEncapsulation.None, 
    providers: [ 
     {provide: 'wsAuthKey', useValue: 'abc'}, 
     {provide: 'wsHost',  useValue: 'efg'}, 
    ], 
}) 
export class DatavizComponent implements OnInit, OnChanges { 

    @ViewChild('chart') private chartContainer: ElementRef; 
    @Input() private graphId:string; 
    @Input() private wsAuthKey:string; 
    @Input() private wsHost:string; 
    @Input() private maxSamples=12; 

    constructor(
     private zms: MetricsService 
    ) { 
    } 

В конструктору, журнале является следующим (значение не передается):

MetricsService constructor= wsAuthKey=blahblah=, wsHost=https://preprod-admin.host.ws 

где он должен показывать «abc» и «efg».

Но мне интересно, нет ли проблемы с компонентом, использующим dataviz componentenet. В этом компоненте, следующая информация были переданы:

@Input() private wsAuthKey:string; 
@Input() private wsHost:string; 

Как я хотел бы тег, необязательно предустановленного хоста и ключ:

   <h1>dataviz volume</h1> 
       <div class="chartContainer left" title="Simultaneous offers via dataviz directive"> 
        <dataviz-offers-volumes 
         id="dataviz-volumes1" 
         [graphId]="graphId" 
         [wsAuthKey]="'myauthkey'" 
         [wsHost]="'http://myhost.com'" 
         [maxSamples]="123" 
        > 
        </dataviz-offers-volumes> 
       </div> 
+0

Где именно вы собираетесь передать эти wsAuthKey и wsHost? Являются ли они конкретными для приложения или конкретного компонента? Не похоже, что вы пытаетесь передать что-либо в своем примере, поэтому неясно, как это должно работать. – estus

+0

Эти данные относятся только к приложению, которое использует компонент (хотя служба предоставляет значения по умолчанию). Я ожидал предоставить их из компонента? (Я добавил небольшой раздел в вопрос) @estus –

+0

Конечно, они не будут определены в конструкторе. Они являются креплениями и недоступны при строительстве. Более того, я не вижу причин для их привязки (Input), они не изменяются. Это полностью зависит от того, как эти значения используются. Есть ли настоящая причина, по которой эти значения должны передаваться через attrs, или вы пытаетесь предоставить эту функцию в случае, если она вам когда-нибудь понадобится? Это существенно усложнит ситуацию. Вам необходимо предоставить подробную информацию о том, как работает MetricsService - например, он, вероятно, не может быть синглом. – estus

ответ

7

Это общий рецепт, который описан в this question в частности. Это должна быть служба, которая имеет конфигурацию:

@Injectable() 
export class MetricsConfig { 
    wsAuthKey = "blahblahblahblahblahblahblahblah="; 
    wsHost = "https://preprod-admin.myservice.ws"; 
} 

@Injectable() 
export class MetricsService { 
    constructor(
     private http: Http, 
     metricsConfig: MetricsConfig 
    ) { 
     this.wsAuthKey = metricsConfig.wsAuthKey; 
     this.wsHost  = metricsConfig.wsHost; 
    } 
} 

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

@Component(
    ... 
    { provide: MetricsConfig, useClass: class ExtendedMetricsConfig { ... } } 
) 
export class DatavizComponent ... 

Там нет реального в этом случае необходимо сделать класс MetricsConfig. Это может быть и поставщик OpaqueToken. Но класс может быть удобно расширен, его легче вводить и уже предоставляет интерфейс для ввода.

+0

Это именно то, что нужно сделать - – chrismarx

14

Вы можете сделать параметры факультативного путем добавления @Optional() (DI) и ? (машинопись) и @Inject(somekey) для примитивных ценностей, которые не поддерживаются в качестве ключей поставщика

@Injectable() 
export class MetricsService { 
    constructor(
     private http: Http, 
     @Inject('wsAuthKey') @Optional() public wsAuthKey?: string, 
     @Inject('wsHost') @Optional() public wsHost?: string 
     ) { 
     this.wsAuthKey = wsAuthKey || "blahblahblahblahblahblahblahblah="; 
     this.wsHost  = wsHost || "https://preprod-admin.myservice.ws"; 
    } 
providers: [ 
    {provide: 'wsAuthKey', useValue: 'abc'}, 
    {provide: 'wsHost', useValue: 'efg'}, 
] 

Если они , они передаются, в противном случае они игнорируются, но DI все еще может вводить MetricsService.

+0

До сих пор так хорошо, за исключением раздела поставщиков: я положил это в компонент, который использует эту услугу, не так ли? –

+0

Вы можете поместить поставщиков в компонент, если сама служба также предоставляется в компоненте. Значения должны быть предоставлены на том же уровне, что и служба или выше. Служба, предоставляемая 'AppModule', не может вводить значения из' MyComponent'. –

+0

Потому что я сделал это, и значение в useValue, предоставленное компонентом, не было передано службе. Я обновляю свой вопрос, чтобы вы могли видеть, где я сейчас @AngularFrance –

Смежные вопросы