简体   繁体   中英

Ember 2.0 How can I make template and route talk to each other?

I am teaching myself Ember-cli and am trying to build a simple application, which fetches results when user searches for a term. I am getting the ajax result just fine, but I am not sure how to "pass" that to the template

This is my hbs code now /app/templates/product-search.hbs:

The search field works just fine.

<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>

This is the route file: /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; 
            });
        }
    }
});

Console o/p:

在此处输入图片说明

and a single object looks like this:

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

So I do see results in my result object but I am still not able to display it in my template. Maybe am not looping over the right object? Or do I need to pass something else? I have no idea what am missing. Any help is appreciated, I've been stuck with this for a couple hours now.

1) You route model hook must return the promise.

Breakdown of what's happening in your code:

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 gets an empty array. As it is not a promise, it assumes it can use it immediately, so it sets it as model and renders the template immediately.

Fixing it:

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
        });
    }
});

This way, you directly return the promise to Ember. Seeing that, Ember knows it must wait for the promise to resolve. When the AJAX call succeeds, the data is passed to the then handler, which returns the actual data to use. In turn, Ember gets that data and sets it for use by the template.

You definitely should read a bit about promises . (Beware though that jQuery's “promises” are not standard).

By the way, I see you are loading ember-data . You should definitely use it instead of $.ajax to load resources. That's what it's for, and it does a much better job of streamlining data models into your Ember workflow.

2) Unless you override it, the data returned by the model hook will be named model in the template.

So just replace results with model in your template and you'll be fine: {{#each model as |item|}}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM