【问题标题】:Ember 2.0 How can I make template and route talk to each other?Ember 2.0 如何使模板和路由相互对话?
【发布时间】:2016-05-10 11:00:00
【问题描述】:

我正在自学 Ember-cli,并尝试构建一个简单的应用程序,当用户搜索一个词时它会获取结果。我得到了 ajax 结果就好了,但我不确定如何将它“传递”给模板

这是我现在的 hbs 代码 /app/templates/product-search.hbs:

搜索栏工作得很好。

<p>*Is 'xyz' by deafult. </p>
{{input class="form-control" id="search-string" type="text" value=this.search-string placeholder="Search by Product"}}
<button type="button" {{action "searchByProduct" this.search-string}}>Lookup Product</button>

<ul>

    {{#each result as |item|}}
        <li>Product Name: {{item.prodName}}</li>
    {{else}}
            Sorry, nobody is here.
    {{/each}}
</ul>

这是路由文件:/app/routes/product-search.js

import Ember from 'ember';

export default Ember.Route.extend({  
    actions: {
        searchByProduct:  function(qString) {
            var term = qString || 'xyz';
            var fetchURL = 'http://some-api.com/search?callback=JSON_CALLBACK&limit=10&term='+term;
            var result = Ember.Object.create({

            });
            return $.ajax({
              url: fetchURL,
              dataType: 'jsonp'
            }).then(function (response) {
                result.set('content', response.results);
                result = result.get('content');
                console.log("Search Result In Then Promise of Model: ");
                console.log(result); //I get an array of objects (screenshot included)
                return result; 
            });
        }
    }
});

控制台操作:

单个对象如下所示:

0: Object
productId: 471744
productName: "xyz"
productViewUrl: "https://someapi.com/us/product/xyz/id471744?uo=4"
imageUrl30: "http://.../source/30x30bb.jpg"
imageUrl60: "http://.../source/60x60bb.jpg"
imageUrl100: "http://.../source/100x100bb.jpg"
collectionId: 700049951
collectionName: "XYZ Collection"
collectionPrice: 9.99
country: "USA"
currency: "USD"
wrapperType: "track"
......
__proto__: Object

所以我确实在我的 result 对象中看到了结果,但我仍然无法在我的模板中显示它。也许没有循环正确的对象?还是我需要传递其他东西?我不知道缺少什么。感谢您提供任何帮助,我已经坚持了几个小时了。

【问题讨论】:

    标签: javascript ajax ember.js jsonp ember-cli


    【解决方案1】:

    1) 你路由model钩子必须返回承诺。

    分解代码中发生的事情:

    export default Ember.Route.extend({
        model: function(params){
            var result = [];              // Create an array
            $.ajax({                      // Start an AJAX request...
              success: function(response){
                result.set('content', response.results);
               }
            });                           // ...but discard the promise
            console.log(result);          // log the array (still empty)
            return result;                // return the array (still empty)
        }
    });                                   // much later, the AJAX call completes but
                                          // Ember does not care.
    

    Ember 得到一个空数组。由于它不是promise,它假设它可以立即使用它,因此将它设置为model并立即渲染模板。

    修复它:

    export default Ember.Route.extend({
        model: function(params){
            var term = 'random';
            var fetchURL = 'http://some-api.com/search?callback=JSON_CALLBACK&limit=10&term='+term;
            return $.ajax({
              url: fetchURL,
              dataType: 'jsonp'
            }).then(function (data) {
                return data.results;   // do whatever processing you have to do
            });
        }
    });
    

    这样,您直接将承诺返回给 Ember。看到这一点,Ember 知道它必须等待 promise 解决。当 AJAX 调用成功时,数据被传递给 then 处理程序,该处理程序返回要使用的实际数据。反过来,Ember 获取该数据并将其设置为供模板使用。

    您绝对应该阅读一下promises。 (请注意,jQuery 的“承诺”不是标准的)。

    顺便说一句,我看到你正在加载ember-data。您绝对应该使用它而不是 $.ajax 来加载资源。这就是它的用途,它在将数据模型简化到您的 Ember 工作流程中做得更好。

    2)除非你覆盖它,否则model钩子返回的数据将在模板中命名为model

    因此,只需在模板中将 results 替换为 model 即可:{{#each model as |item|}}

    【讨论】:

    • 我尝试了您建议的方式,通过使用 then 捕获结果并确保我实际上没有丢失数据集,但我的 data 对象仍然是空的.. console.log(data) 在then 方法返回一个带有空 results 数组的对象
    • 在这种情况下,这意味着服务器返回的内容有问题。 then 方法中的 data 对象将是 jQuery 返回的任何内容。您将类型设置为jsonp,您确定服务器实际上返回的是 jsonp 而不是其他东西,如常规 json?
    • 所以我现在得到了结果,请参阅更新,但仍然无法在我的模板中呈现它。
    • 我看到你改变了你的例子,你现在从一个动作中调用 ajax 请求。它的工作方式与模型不同。在一个动作中,你必须调用this.transitionTo('routename', model)。其中routename 是路线名称,model 是您的结果。
    • 嗯,你能描述得更详细一点吗?我知道在我的情况下,这将转化为:this.transitionTo('search-product', result),但不确定当前代码中替换了什么或有什么问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多