2017-02-20 9 views
2

Я пытаюсь реализовать простую автозагрузку в компоненте. Я тестирую fastboot и поэтому использую ember-сеть для связи с моим API. Сейчас я не использую данные ember. Независимо от того, является ли это «ember» способ сделать это, это другой вопрос ... Я просто пытаюсь заставить это работать.Ember: обработка JSON-ответа от обещания ember-сети в компоненте

Мой компонент 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 для этого варианта использования. Вы можете посмотреть на auto complete feature explanation doc

Ваш код компонента,

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> 

Option2. Вы можете вернуть 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) 
     }); 
    }) 
}); 

Ссылка уголек воспламенитель article- The Guide to Promises in Computed Properties

+1

вещь параллелизма действительно интересна. Я посмотрел на него и сразу подумал, что это не сработает с fastboot, но это так! Я думаю, что это будет очень удобно в будущем. благодаря! – tarponjargon

0

Прежде всего, ИМО, это не очень хорошая практика, чтобы вызвать удаленный вызов от вычисляемого свойства. Вы должны запустить его из входного компонента/помощника.

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

Хорошо, это имеет смысл. Я думаю, что «searchResults» по-прежнему в конечном счете является неистребимым обещанием, хотя, правильно? Я думаю, что предложение кумканиллама PromiseObject нужно будет обработать, правильно? – tarponjargon

+0

Нет, 'searchResults' будет массивом результатов (iterable). – ykaragol