【问题标题】:Get data to template from Service从服务获取数据到模板
【发布时间】:2016-01-16 17:24:45
【问题描述】:

我需要绑定来自服务的模板数据变量。服务使用 HTTP 以 JSON 格式检索数据。我得到了正确的数据,但是因为请求是如此异步返回的服务总是未定义的。

如何将异步数据出售到模板中?不使用回调?

应用组件:

    import {Component} from 'angular2/core';
    import {RouteConfig, Router, ROUTER_DIRECTIVES} from 'angular2/router';
    import {SystemComponent} from "./system.component";
    import {MenuProvider} from "./providers/menuprovider";
    import {Menu} from "./entity/menu";
    import {Http, Headers, HTTP_PROVIDERS} from 'angular2/http';

    @Component({
        selector: 'app',
        templateUrl: '/templates/layout',
        directives: [ROUTER_DIRECTIVES]
    })

    @RouteConfig([
        {
            path: '/',
            redirectTo: ['/System'],
            useAsDefault: true
        },
        {
            path: '/-1/...',
            name: 'System',
            component: SystemComponent
        }
    ])



    export class AppComponent {

        menusItems:Array<Menu>;

        constructor(router: Router, menuProvider:MenuProvider){
            this.menusItems = menuProvider.getMenuItems(1);
            router.navigate(['/System']);
        }
    }

菜单提供者:

    import {Menu} from "../entity/menu";
    import {IndexedCollection} from "../collections/IndexedCollection";
    import {Injectable}    from 'angular2/core'
    import {Http, Headers, HTTP_PROVIDERS} from 'angular2/http';

    @Injectable()
    export class MenuProvider{

        _menuItems:Array<Menu>;

        private _http:Http;

        constructor(http:Http){
            this._http = http;
        }

        getMenuItems(shopId:number){
            this.loadMenuForShopId(shopId);
            return this._menuItems;
        }

        private loadMenuForShopId(shopId:number){
            var base = this;
            this._http.get('/services/menu/list/' + shopId)
                .subscribe(
                  function(res){
                      res = res.json();
                      for(index in res['menuItems']){
                          var menu = res['menuItems'][index];
                          base._menuItems.push(new Menu(menu['url'], menu['name']));
                      }
                  }
                );
        }
    }

菜单实体:

     export class Menu{

        private _url;

        private _name;

        constructor(url:string,name:string){
            this._url = url;
            this._name = name;
        }

        get url() {
            return this._url;
        }

        get name() {
            return this._name;
        }
    }

模板:

        <ul>
            <li  *ngFor="#menu of menusItems">
                <a>{{menu.getName()}}</a>
            </li>
        </ul>

【问题讨论】:

  • 你可以返回 observable 并在 Controller 中订阅它。 observable 将立即交付,您可以选择在信息返回控制器后如何处理。

标签: angular


【解决方案1】:

看看Observable;这是你最好的新朋友 (;

您可以使“冷”可观察(只需描述它应该做什么):

getMenuItems(shopId:number){
  return this._http
    .get('/services/menu/list/' + shopId)
    .map(res => res.json())
    .map(res => {
      let menu = res.menuItems;
      return new Menu(menu.url, menu.name)
    })
}

... 并让 Angular 使用 AsyncPipe 订阅它:

<ul>
  <li  *ngFor="#menu of menusItems |async">
    <a>{{menu.getName()}}</a>
  </li>
</ul>

AsyncPipe 适用于可观察对象、承诺和事件...

transform(obj: Observable<any>| Promise<any>| EventEmitter<any>, args?: any[]) : any

【讨论】:

  • .map() 不是函数:X
  • 这是一个different issue。您需要导入地图运算符...
  • 如何将其用于 1 件商品?我的简单代码:pastebin.com/K1rEYeNj 错误:异常:TypeError: undefined is not an object (evaluate 'l_currentShop0.name') in [{{currentShop.name}} in AppComponent@22:12]
  • 您可以在模板中使用Elvis operator&lt;div&gt;{{currentShop?.name}}&lt;/div&gt;
【解决方案2】:

请不要使用同步 HTTP 请求。这可能会阻止您的浏览器在请求完成之前运行任何代码。

在我看来,最好的解决方案是保持请求异步,但在您检索数据时向用户显示一条消息,例如“正在加载...”。

您可以使用 ngIf 指令和一个在请求完成后将变为 true 的变量。

【讨论】:

  • 此外,浏览器供应商正在弃用同步 XmlHttpRequest 并已在开发工具控制台中放置警告。同步代码方法将被打破的一天很快就会到来
猜你喜欢
  • 1970-01-01
  • 2021-12-16
  • 2011-06-29
  • 2018-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-08
相关资源
最近更新 更多