2017-07-20 13 views
2

Ajax呼び出しから取得するテキストボックスに入力するときにリストをフィルタリングしようとしています。この問題は、Ajaxの準備が整う前にフィルタが適用されているようです。Vue検索入力時にAjax応答配列

HTML:

<input type="text" class="form-control" v-model="searchTerm"> 
<table> 
    <tr v-for="food in filteredItems"> 
     <td>{{ food.name }}</td> 
     <td>{{ food.energy }}</td> 
    </tr> 
</table> 

ヘルパー/ index.js:

export default { 
    getFoods() { 
    return Vue.http.get('http://localhost:3000/foods/allfoods') 
     .then((response) => { 
      return response.data; 
    }); 
    } 
} 

Vueのコンポーネント:

import helpers from '../helpers' 
export default { 
    name: 'Search', 
    mounted() { 
    helpers.getFoods().then((response) => { 
     this.foodData = response; 
    }); 
    }, 
    data() { 
    return { 
     searchTerm: '', 
     foodData: [], 
    } 
    }, 
    computed: { 
    filteredItems() { 
     return this.foodData.filter(function(food){return food.name.toLowerCase().indexOf(this.searchTerm.toLowerCase())>=0;}); 
    } 
    } 

私はページをロードしたり、私が

'TypeError: undefined is not an object (evaluating 'this.searchTerm')'.

を取得する入力を開始

foodData配列をハードコードするとすべてが正常に動作します。

私は何か誤解していましたか、何が間違っていますか?

+0

2つの質問:1. 'filteredItems'の' this'参照を修正しようとしましたか? 2.どのように 'searchTerm'を設定しますか?私はあなたのテンプレートでそれを見ていないよ。 –

+0

ここに忘れてしまったHTMLにの不足を追加しました。あなたはこの参照を修正することで何を意味するのか説明できますか? –

+0

バートは言った;) –

答えて

0

計算されたフィルタ関数のコールバックで、thisがVueを指していません。

computed: { 
    filteredItems() { 
    return this.foodData.filter(function(food){ 
     // in this next line, this.searchTerm is likely undefined 
     // because "this" is not the Vue 
     return food.name.toLowerCase().indexOf(this.searchTerm.toLowerCase()) >= 0; 
    }); 
    } 
} 

あなたがコールバックとしてfunction(food){...}を使用しているためです、とthisは含む範囲となります。代わりに、矢印関数、クロージャ、またはbindを使用します。

computed: { 
    filteredItems() { 
    return this.foodData.filter(food => { 
     // in this next line, this.searchTerm is likely undefined 
     // because "this" is not the Vue 
     return food.name.toLowerCase().indexOf(this.searchTerm.toLowerCase()) >= 0; 
    }); 
    } 
} 

console.clear() 
 

 
const foods = [{ 
 
    name: "orange", 
 
    energy: 10 
 
    }, 
 
    { 
 
    name: "apple", 
 
    energy: 8 
 
    }, 
 
    { 
 
    name: "banana", 
 
    energy: 12 
 
    }, 
 
    { 
 
    energy: 1000 
 
    } 
 
] 
 

 
const Search = { 
 
    name: 'Search', 
 
    template: ` 
 
     <div> 
 
     <input type="text" class="form-control" v-model="searchTerm"> 
 
     <table> 
 
      <tr v-for="food in filteredItems"> 
 
      <td>{{ food.name }}</td> 
 
      <td>{{ food.energy }}</td> 
 
      </tr> 
 
     </table> 
 
     </div> 
 
    `, 
 
    mounted() { 
 
     setTimeout(() => this.foodData = foods, 500) 
 
    }, 
 
    data() { 
 
     return { 
 
     searchTerm: '', 
 
     foodData: [], 
 
     } 
 
    }, 
 
    computed: { 
 
     filteredItems() { 
 
     const searchTerm = this.searchTerm.toLowerCase() 
 
     return this.foodData 
 
      .filter(food => food.name && food.name.toLowerCase().includes(searchTerm)) 
 
     } 
 
    } 
 
    } 
 
new Vue({ 
 
    el:"#app", 
 
    components: {Search} 
 
})
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script> 
 
<div id="app"> 
 
    <search></search> 
 
</div>

How to access the correct this inside a callbackを参照してください。

+0

あなたの答えをありがとう。しかし、残念ながらそれで解決できませんでした。矢印関数に切り替えると、 'TypeError:未定義はオブジェクトではありません(' food.name.toLowerCase 'を評価しています)' リンクをありがとうございます。それは間違いなく読む価値があります。 –

+0

@ArtoSaarinenすべてのあなたの 'food'オブジェクトは' name'を持っていますか? – Bert

+0

@ArtoSaarinen実例を追加しました(シミュレートされたAPI呼び出しを使用)。違いがどこにあるかを見てください。 – Bert

関連する問題