2016-08-17 3 views
0

Я разрабатываю приложение с угловым 2 RC4 (ключевое слово RC4), и я разработал компонент, который я хочу использовать там, где и когда это необходимо.Инициализация компонента с ошибкой NoProvider

Для этого я разработал этот простой компонент:

import { Component, Input, OnInit, OnDestroy } from '@angular/core'; 
import { Panel } from 'primeng/primeng'; 

@Component({ 
    selector: "bb-tile", 
    templateUrl: "app/shared/tile/index.html", 
    directives: [Panel] 
}) 

export class BbTile{ 
    @Input() title: string; 
    @Input() value: string; 

    constructor(title: string, value: string) { 
     this.title = title; 
     this.value = value; 
    } 
} 

И это мой шаблон:

<p-panel class="boxesdashboard"> 
    <header> 
     {{title}} 
    </header> 
     {{value}} 
</p-panel> 

Затем я называю этот компонент внутри другого компонента с помощью этого кода:

import { Component } from '@angular/core'; 
import { HTTP_PROVIDERS } from '@angular/http'; 
(...) 
import { BbTile } from "./../../../shared/tile/tile.component"; 

@Component({ 
templateUrl: 'app/pages/users/dashboard/index.html', 
selector: 'my-app', 
// Honestly I'm not sure if all of these are required here 
directives: [InputText, DataTable, Button, Dialog, Column, Header, Footer, Panel, ProgressBar, Dropdown, 
    SplitButton, SplitButtonItem, Toolbar, SelectButton, OverlayPanel, Checkbox, ToggleButton, BbTile], 
providers: [HTTP_PROVIDERS, UsersService] 

})

export class UsersDashboardComponent { 
    // Data variables 
    user: User = new PrimeUser(); 
    selectedUser: User; 
    newUser: boolean; 
    users: User[] = []; 

    tiles: BbTile[] = [new BbTile("Celso", "300"), new BbTile("ZéTó", "400")]; 
    (...) 
} 

И на моем userDashboardComponent HTML, я следующее:

<h1 class="ui-g-12 titlebox">Users Dashboard</h1> 
    <div class="ui-g-6 tiles-flex-wrap"> 
     <bb-tile *ngFor="let t of tiles" [tile]="tile"></bb-tile> 
    </div> 
</h1> 

Однако всякий раз, когда я запускаю это я получаю кучу ошибок в моей консоли относительно NoProviderExceptions:

browser_adapter.ts:82 EXCEPTION: Error in app/pages/users/dashboard/index.html:20:3BrowserDomAdapter.logError @ browser_adapter.ts:82BrowserDomAdapter.logGroup @ browser_adapter.ts:93ExceptionHandler.call @ exception_handler.ts:58(anonymous function) @ application_ref.ts:374schedulerFn @ async.ts:148SafeSubscriber.__tryOrUnsub @ Subscriber.ts:240SafeSubscriber.next @ Subscriber.ts:192Subscriber._next @ Subscriber.ts:133Subscriber.next @ Subscriber.ts:93Subject._finalNext @ Subject.ts:154Subject._next @ Subject.ts:144Subject.next @ Subject.ts:90EventEmitter.emit @ async.ts:133onError @ ng_zone.ts:142onHandleError @ ng_zone_impl.ts:95ZoneDelegate.handleError @ zone.js:336Zone.runTask @ zone.js:268drainMicroTaskQueue @ zone.js:491ZoneTask.invoke @ zone.js:435 browser_adapter.ts:82 ORIGINAL EXCEPTION: No provider for String!BrowserDomAdapter.logError @ browser_adapter.ts:82ExceptionHandler.call @ exception_handler.ts:70(anonymous function) @ application_ref.ts:374schedulerFn @ async.ts:148SafeSubscriber.__tryOrUnsub @ Subscriber.ts:240SafeSubscriber.next @ Subscriber.ts:192Subscriber._next @ Subscriber.ts:133Subscriber.next @ Subscriber.ts:93Subject._finalNext @ Subject.ts:154Subject._next @ Subject.ts:144Subject.next @ Subject.ts:90EventEmitter.emit @ async.ts:133onError @ ng_zone.ts:142onHandleError @ ng_zone_impl.ts:95ZoneDelegate.handleError @ zone.js:336Zone.runTask @ zone.js:268drainMicroTaskQueue @ zone.js:491ZoneTask.invoke @ zone.js:435 browser_adapter.ts:82 ORIGINAL STACKTRACE:BrowserDomAdapter.logError @ browser_adapter.ts:82ExceptionHandler.call @ exception_handler.ts:74(anonymous function) @ application_ref.ts:374schedulerFn @ async.ts:148SafeSubscriber.__tryOrUnsub @ Subscriber.ts:240SafeSubscriber.next @ Subscriber.ts:192Subscriber._next @ Subscriber.ts:133Subscriber.next @ Subscriber.ts:93Subject._finalNext @ Subject.ts:154Subject._next @ Subject.ts:144Subject.next @ Subject.ts:90EventEmitter.emit @ async.ts:133onError @ ng_zone.ts:142onHandleError @ ng_zone_impl.ts:95ZoneDelegate.handleError @ zone.js:336Zone.runTask @ zone.js:268drainMicroTaskQueue @ zone.js:491ZoneTask.invoke @ zone.js:435 browser_adapter.ts:82 Error: DI Exception at NoProviderError.BaseException [as constructor] (exceptions.ts:21) at NoProviderError.AbstractProviderError [as constructor] (reflective_exceptions.ts:59) at new NoProviderError (reflective_exceptions.ts:92) at ReflectiveInjector_._throwOrNull (reflective_injector.ts:849) at ReflectiveInjector_._getByKeyDefault (reflective_injector.ts:878) at ReflectiveInjector_._getByKey (reflective_injector.ts:840) at ReflectiveInjector_.get (reflective_injector.ts:633) at ElementInjector.get (element_injector.ts:23) at ElementInjector.get (element_injector.ts:23) at ReflectiveInjector_._getByKeyDefault (reflective_injector.ts:876)

Что я здесь делаю неправильно? Я был над документами, и единственное различие, которое я вижу, - это то, что в примерах используется служба/поставщик для ввода данных, где я действительно этого не хочу, я хочу иметь возможность непосредственно инициализировать значения.

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

Помогите пожалуйста?

ответ

1

Недвижимость вашего компонента BbTile называется title, а не tile !! И вы должны привязать каждое значение и не можете просто поставить весь объект.

Используйте это так:

<bb-tile *ngFor="let t of tiles" [title]="t.title" [value]="t.value"></bb-tile>

Если вы хотите использовать его как пути (что я вымышленным) .. Вам нужно изменить его немного ..

export class BbTileModel { 
    public title: string; 
    public value: string; 

    constructor (... init stuff here ...) { ... } 
} 

@Component({ 
    selector: "bb-tile", 
    templateUrl: "app/shared/tile/index.html", 
    directives: [Panel] 
}) 

export class BbTile { 
    @Input() tile: BbTileModel; 

    constructor() { } 
} 

Шаблон:

<p-panel class="boxesdashboard"> 
    <header> 
     {{tile.title}} 
    </header> 
     {{tile.value}} 
</p-panel> 

массив будет выглядеть так:

tiles: BbTileModel[] = [new BbTileModel("Celso", "300"), new BbTileModel("ZéTó", "400")];

и, наконец, ваш ngFor:

<bb-tile *ngFor="let t of tiles" [tile]="t"></bb-tile>

Просто написал здесь, так что его не копировать и вставлять готовый, но вы должны получить идею за ним! :)

+0

Мне нравится этот подход лучше. Спасибо @mxii –

1

Конкретная ошибка, которую вы получаете, возникает из-за конструктора. Конструктор требует два строковых ввода.Когда экземпляр компонента создается, он создается за кулисами Angular. Если Angular видит, что есть параметры, необходимые для конструктора, он просмотрит список Провайдеров, чтобы найти подходящего Провайдера, чтобы сгенерировать данные для ввода в конструктор. В вашем случае у вас нет инъекционных поставщиков, которые производят строки, чтобы вы получили ошибку.

Важнейшей проблемой, которую вы имеете здесь, является проблема с дизайном. Вы пытаетесь использовать один и тот же объект (BbTile) как объект хранения данных, который вы используете для хранения значений (tiles: BbTile[] = [new BbTile("Celso", "300"), new BbTile("ZéTó", "400")];), так и визуальный компонент, используемый Angular для отображения значений. Вы не должны этого делать. Для нужд хранения данных вам нужен конструктор, который принимает строковые параметры, тогда как для компонента вам нужен пустой конструктор (данные поступают через аннотированные свойства @Input()). Существует также тот факт, что вы несете дополнительный багаж компонента со своим хранилищем данных (и, возможно, путаницу, когда вы считаете, что экземпляр BbTile используется для отображения, когда он создан с помощью нового BbTile (...), чего бы не было).

Вместо этого, используйте массив различных объектов (или строки) для хранения плитки [] в UsersDashboardComponent, может быть что-то вроде:

tiles: any[] = [{"title": "Celso", "value": "300"}, {"title":"ZéTó", "value":"400"}]

Затем вы передаете значения в BbTile с использованием параметров HTML (которые получают подключен к свойствам @Input на экземпляре BbTile угловому делает для вас):

<h1 class="ui-g-12 titlebox">Users Dashboard</h1> 
    <div class="ui-g-6 tiles-flex-wrap"> 
     <bb-tile *ngFor="let t of tiles" [title]="t.title" [value]="t.value"></bb-tile> 
    </div> 
</h1> 

Ваш BbTile будет оставаться в основном то же самое, но будет иметь пустой конструктор:

@Component({ 
    selector: "bb-tile", 
    templateUrl: "app/shared/tile/index.html", 
    directives: [Panel] 
}) 

export class BbTile{ 
    @Input() title: string; 
    @Input() value: string; 

    constructor() { } 
} 
+0

Упрощенный, потому что это правильный ответ. Тем не менее, я буду принимать ответ @ mxii, поскольку он более полно подходит к этому конкретному варианту использования. Tks –

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