2016-04-22 37 views
17

任何人都可以帮助查看在我的模板中是否存在语法错误?它不会给出错误,但不会将数据填充到模板中。angular2异步管道不会将对象数据填充到模板中

<div *ngIf="(hero | async)"> 
    <h2>{{hero}}</h2> 
    <h2>{{hero.name}} details!</h2> 
    <div> 
    <label>_id: </label>{{hero._id}}</div> 
    <div> 
    <label>name: </label> 
    <input [(ngModel)]="hero.name" placeholder="name" /> 
    </div> 
    <button (click)="goBack()">Back</button> 
</div> 

元器件代码

export class HeroDetailComponent implements OnInit { 
    errorMessage: string; 

    //@Input() 
    hero: Observable<Hero>; 

    constructor(
     private _heroService: HeroService, 
     private _routeParams: RouteParams) { 
    } 

    ngOnInit() { 
     let _id = +this._routeParams.get('_id'); 
     this._heroService.loadHero(_id); 
     this.hero = this._heroService.hero$; 
     this.hero.subscribe(data => 
      console.log(data) 
     ) 
    } 

的的console.log(数据)打印 对象{_id:11,名称: “好先生”}其中我说,数据被正确地检索 。

<div>块也显示出来,这意味着* ngIf将该对象视为非空。

<h2>{{hero}}</h2>显示[object Object]。

但为什么{{hero.name}}不显示?

+0

你有几件事情混为一谈。 'hero'是一个输入属性,但是你在ngOnInit()中赋值它 - 这很奇怪。赋值是一个Observable,它没有'name'属性,这就解释了为什么'{{hero.name}}'不起作用。这个答案应该可以帮助你:http://stackoverflow.com/a/34561532/215945 –

+0

我更新了帖子并删除了@input。但仍然如此。异步管道应该把观察者变成英雄对象? – Shawn

回答

48

对象与异步管道有点棘手。使用包含数组的Observable,我们可以使用NgFor并创建一个本地模板变量(下面的hero),在异步管道从Observable提取数组后,该变量被分配给数组中的每个项目。然后,我们可以使用该变量在其他地方的模板:

<div *ngFor="let hero of heroes | async"> 
    {{hero.name}} 
</div> 
<!-- we can't use hero here, outside the NgFor div --> 

但随着包含单个对象可观察到的,我不知道有任何的方式来创建一个本地模板变量,该变量引用的对象。相反,我们需要做一些更复杂的事情:

<div>{{(hero | async)?.name}}</div> 

而且我们需要重复说明我们要显示的对象的每个属性。 (以上行假定组件属性hero是可观察到的。)

这可能是更容易分配对象(即所述可观测的内部,下面hero$)与组分的性质,使用分量逻辑:

this._heroService.hero$.subscribe(data => this.hero = data.json()); 

,然后使用NgIf或Elvis/safe navigation operator在视图中显示的数据:

<div *ngIf="hero">{{hero.name}}</div> 
<!-- or --> 
<div>{{hero?.name}}</div> 
+0

{{(hero | async)?. name}}不起作用。我做了第二种方式:订阅将数据获取到组件属性并在模板中引用它。感谢您抽出宝贵的时间。我很感激。 – Shawn

+3

{{(hero | async)?.name}}
- 这是完美的。为我节省了大量的时间... –

+0

真棒,第二种方式更容易和直接:) –

19

另一种选择是使用@input和杠杆智能/哑组件的方法。在智能组件中,您可以将异步对象传递给哑元组件,然后在愚蠢组件中将其用作普通对象。

这个想法是,你的智能组件处理逻辑和数据,哑组件处理演示。

智能组件:

<dumb-component [myHero]="hero$ | async"></dumb-component> 

阿呆组件类:

@Input() myHero: Hero; 

阿呆组件模板:

<div>{{ myHero.name }}</div> 
+2

这在我看来是正确的方法 – Amit

+0

为我节省了很多时间,并且比接受的答案更好的解决方案恕我直言。 – mdziob

+0

myHero是一个字符串吧?难道不是'

{{ myHero }}
'而不是'
{{ myHero.name }}
'? – guilhebl

1

我只是添加了如何使用智能/哑精度在需要使用异步管道和括号语法的情况下使用组件方法。

这结合了一个技巧发现here

< ui-gallery-image([image]="(imagesFB | async) ? (imagesFB | async)[0] : null") ></ui-gallery-image>

我已经花时间找。希望这个帮助。 有关此信息blog post

14

这是现在可以使用 '为' 语法,可用在V4.0.0:

<span *ngIf="user$ | async as user; else loadingUserInfo"> 
{{user.firstName}} {{user.lastName}} 
</span> 
<ng-template #loadingUserInfo> 
    Loading user information... 
</ng-template> 

RFC thread on github提供更多细节。

1

在Angular 2.3.x或Angular 4.x模板中处理单个可观察对象的最佳方式是使用具有模板变量的异步管道。

这是角度开发人员的共同目标。从redux中获取一组元素,并从集合中抽取一个匹配元素。然后在模板中渲染单个对象。

COMPONENT

@Component({ 
    selector: 'app-document-view', 
    templateUrl: './document-view.component.html', 
    styleUrls: ['./document-view.component.scss'] 
}) 
export class DocumentViewComponent implements OnInit { 

    @select(['documents', 'items']) readonly documenList$: Observable<DocumentDTO[]>; 
    public documentVO$: Observable<DocumentDTO>; 

    constructor(private _state: NgRedux<IAppState>, 
       private _route: ActivatedRoute, 
       private _documentActions: DocumentActions) { 

    _route.params.subscribe(params => { 
     let modelId: number = parseInt(params['modelId']); //1   
     let documentId: number = parseInt(params['documentId']); //50 
     this._documentActions.getDocument(modelId, documentId); 
    }); 
    } 

    ngOnInit() { 

    //documenList holds all of the documents in our application state 
    //but this view only wants a single element 

    this.documentVO$ = this.documenList$.map(documents => documents.find(doc => doc.documentId === 50)); 
    } 
} 

VIEW

<div class="row" *ngIf="documentVO$ | async as dto"> 
    <div id="about" class="col-12"> 
     <div id="title" class="paper meta"> 
      <p>{{ dto.title }}</p> 
     </div> 
    </div> 
</div>