2017-02-20 14 views
2

コンポーネントに簡単な自動擬似を実装しようとしています。私はfastbootをテストしているので、ember-networkを使って自分のAPIと通信しています。今私はember-dataを使用していません。これを行うための "エバー(ember)"方法であるかどうかは、別の質問です...私はこれを動作させようとしています。Ember:コンポーネントでember-network promiseからJSON応答を処理する

マイコンポーネントJS:

import Ember from 'ember'; 
import fetch from 'ember-network/fetch'; 

export default Ember.Component.extend({ 
    searchText: null, 

    loadAutoComplete(query) { 
     let suggestCall = 'http://my.api.com/suggest?s=' + query; 
     return fetch(suggestCall).then(function(response) { 
      return response.json(); 
     });  
    }, 

    searchResults: Ember.computed('searchText', function() { 
     let searchText = this.get('searchText'); 
     if (!searchText) { return; } 
     let searchRes = this.loadAutoComplete(searchText); 
     return searchRes; 
    }) 
}); 

、テンプレートで:

{{input type="text" value=searchText placeholder="Search..."}} 

{{ log "TEMPALTE RESULTS" searchResults }} 
{{#each-in searchResults as |result value|}} 
<li>{{result}} {{value}}</li> 
{{/each-in}} 

テンプレートログディレクティブは私のコンソールでこれを出力している:

console

データがあります「提案」の中で、フェッチが機能していることを知っています。私はちょうどそれを得る方法を理解できません。私は '_result'をループすることはできません。これを解析してテンプレートで使用するには、私は何をする必要がありますか?計算されたプロパティから

答えて

3

戻る約束は、それは少しトリッキーです、ただまっすぐではありません。

オプション1。このユースケースにはember-concurrencyアドオンを使用できます。あなたは

import Ember from 'ember'; 
import { task, timeout } from 'ember-concurrency'; 

export default Ember.Component.extend({ 
    searchText: null, 

    searchResults: task(function*(str) { 
     this.set('searchText', str); 
     let url = `http://my.api.com/suggest?s=${str}`; 
     let responseData = yield this.get('searchRequest').perform(url); 
     return responseData; 
    }).restartable(), 
    searchRequest: task(function*(url) { 
     let requestData; 
     try { 
      requestData = Ember.$.getJSON(url); 
      let result = yield requestData.promise(); 
      return result; 
     } finally { 
      requestData.abort(); 
     } 
    }).restartable(), 
}); 

とコンポーネントのHBSコード、

<input type="text" value={{searchText}} onkeyup={{perform searchResults value="target.value" }}> 
<div> 
    {{#if searchResults.isIdle}} 
     <ul> 
      {{#each searchResults.lastSuccessful.value as |data| }} 
      <li> {{data}} </li> 
      {{else}} 
      No result 
      {{/each}} 
     </ul> 
    {{else}} 
     Loading... 
    {{/if}} 
</div> 

オプション2、auto complete feature explanation doc

あなたのコンポーネントのコードを見ることができます。あなたはDS.PromiseObjectまたはDS.PromiseArray

import Ember from 'ember'; 
import fetch from 'ember-network/fetch'; 

export default Ember.Component.extend({ 
    searchText: null, 

    loadAutoComplete(query) { 
     let suggestCall = 'http://my.api.com/suggest?s=' + query; 
     return fetch(suggestCall).then(function(response) { 
      return response.json(); 
     }); 
    }, 

    searchResults: Ember.computed('searchText', function() { 
     let searchText = this.get('searchText'); 
     if (!searchText) { return; } 
     //if response.json returns object then you can use DS.PromiseObject, if its an array then you can use DS.PromiseArray   
     return DS.PromiseObject.create({ 
      promise: this.loadAutoComplete(searchText) 
     }); 
    }) 
}); 

IMO、計算されたプロパティからのリモートコールを呼び出すことをお勧めではありませんすべてのThe Guide to Promises in Computed Properties

+1

同時実行事は本当に面白いです。私はそれを見てすぐにそれがfastbootで動作しないと思ったが、それはそうである!私はこれが将来的にはとても便利だと思います。ありがとう! – tarponjargon

0

まず、article-点火燃えさしリファレンスを返すことができます。入力コンポーネント/ヘルパーからトリガする必要があります。

{{input type="text" value=searchText placeholder="Search..." key-up=(action loadAutoComplete)}} 

そして新しいloadAutoCompleteは次のようになります:

loadAutoComplete(query) { 
    //check query is null or empty... 
    let suggestCall = 'http://my.api.com/suggest?s=' + query; 
    return fetch(suggestCall).then((response) => { 
     this.set('searchResults', response.json()); 
    });  
}, 

あなたsearchResultsはもはや計算されたプロパティが必要になります。ただの財産。

+0

OKです。私は 'searchResults'はまだ究極的には反復可能な約束だと思いますが、正しいのでしょうか?私はkumkanillamのPromiseObjectの提案が正しく機能する必要があると思いますか? – tarponjargon

+0

いいえ、 'searchResults'は結果配列(iterable)になります。 – ykaragol

関連する問題