我正在开发一个使用Angular 2 RC4的应用程序(这里的关键字是RC4),我已经开发了一个我希望在需要的地方和时间使用的组件。
为此,我开发了这个简单的组件:
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线程没有提供答案。
有人可以帮忙吗?
答案 0 :(得分: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>
刚刚在这里写下来,所以不要复制和粘贴准备好了,但你应该明白它背后的想法! :)
答案 1 :(得分:1)
您获得的具体错误是由于构造函数。构造函数需要两个字符串输入。创建组件实例时,它将由Angular在幕后创建。如果Angular发现构造函数需要参数,它将查看提供者列表以查找匹配的Provider以生成要注入构造函数的数据。在您的情况下,您没有可生成字符串的可注入提供程序,因此您会收到错误。
您在这里遇到的更重要的问题是设计问题。您尝试使用相同的对象(BbTile)作为用于存储值(tiles: BbTile[] = [new BbTile("Celso", "300"), new BbTile("ZéTó", "400")];
)的数据保持对象和Angular用于显示值的可视组件。你不应该这样做。对于数据存储需求,您最终需要一个带有字符串参数的构造函数,而对于组件,您需要一个空构造函数(数据通过@Input()带注释的属性进入)。还有一个事实是你携带一个组件的额外行李与你的数据存储(当你认为BbTile的一个实例是你使用新的BbTile(...)创建时,可能会出现混乱),不会是这种情况。)
相反,使用不同对象(或字符串)的数组来存储UsersDashboardComponent中的tile [],可能是这样的:
tiles: any[] = [{"title": "Celso", "value": "300"}, {"title":"ZéTó", "value":"400"}]
然后使用HTML参数将值传递给BbTile(它连接到BbTile Angular实例上的@Input属性):
<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() { }
}