0

I'm stuck in -maybe- logic usage of Vue, I have a "list" component which get results from ajax, the problem appears when I want to add a search field, I have something like this:

search.vue

<template>
  <div>
    <div v-for="(result, index) in results">
      <h2>{{ result.name }}</h2>
    </div>
  </div>
</template>

<script>
  export default {
    name : 'searchList',

    data() {
      return { results: [] }
    }

    created: function(){
      this.goSearch();
    },

    methods : {
      goSearch : function(){
        this.results = axios.get('/search');
      }
    }
  }
</script>

This works like a charm, the point is that I want to add an input to search, I've made some research and I've found that the only way to get this is using another component, but I don't want to create another component just for an input, so I want to do something like:

index.html

<input type="text" v-model="goSearch">

<search-list></search-list>

But the problem that I'm facing is that Vue is returning an error:

[Vue warn]: Property or method "goSearch" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

I've also tried with v-bind="goSearch" but doesn't work either. Any ideas to accomplish this?

UPDATE: I've created a button to call the function:

<button @click="goSearch"></button>

The function "goSearch" now tries to get the value from the text box, but also this doesn't work.

2
  • @Core972 I've read that, but as far as I know prop is only for child component to parent component, isn't it? Commented Jun 11, 2018 at 19:01
  • Your created and methods keys are out of the exported object. Do not you get a parse error? Commented Jun 11, 2018 at 19:09

2 Answers 2

0

You're getting such error because you're using:

<input type="text" v-model="goSearch">

Here, the goSearch is data and this data is not found by vue. But you meant it to be a method. Vue doesn't work like that. You will not require to use v-model if you want to bind some method in it. But you will need to bind v-on:input

<input type="text" v-on:input="goSearch">
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your answer but also Vue returns the same error and adding a new one: [Vue warn]: Invalid handler for event "input": got undefined
0

The problem is that the goSearch method is defined inside the searchList component, anything outside of it doesn't know what it is (in this case, the input element), hence the warn.

A solution would be defining the method in the parent component (in this case, seems like it's index.html), so all children components can access it.

You would also have to store the results array inside the parent data and send it to the searchList component using props together with the goSearch function, like so:

search.vue

<template>
    <div>
        <div v-for="(result, index) in results" v-bind:key="index">
            <h2>{{ result.title }}</h2>
        </div>
    </div>
</template>

<script>
  export default {
    name: 'searchList',
    props: ['results'],
    created: function () {
      this.$emit('goSearch')
    }
  }
</script>

Parent component:

<template>
  <div id="app">
    <button v-on:click="goSearch">Get Random Post</button>
    <search-list
            v-on:goSearch="goSearch"
            v-bind:results="results"
    ></search-list>
  </div>
</template>

<script>
import searchList from './components/searchList'

export default {
  name: 'App',
  data () {
    return { results: [] }
  },
  components: {
    searchList
  },
  methods: {
    goSearch: function () {
      const postId = Math.floor(Math.random() * (100 - 1 + 1)) + 1
      fetch('https://jsonplaceholder.typicode.com/posts/' + postId)
        .then(response => response.json())
        .then(json => {
          this.results = [json]
        })
    }
  }
}
</script>

Keep in mind that if more than one component uses the property/method, you need to define it in a parent component, then you send that info to the children components using props and the children can trigger events of that parent using emit.

enter image description here

Also, check out this answer.

11 Comments

This an excellent answer, but I can't unify the input and the results, because they have some html structure and put both together implies that I have to put all the HTML in vue template. Also, using $emit('goSearch'); returns an error: [Vue warn]: Error in created hook: "ReferenceError: $emit is not defined", I think that you are talking about using two components, something that I don't want to do, but it seems that's a must.
How so? What happens?
I just update my comment. Sorry I hit enter prematurely.
May I ask, is everything wrapped inside the export default object?
Yes, it is. As a part of the component. In my app.js I just call it: Vue.component('search-list', require('./components/SearchList.vue')); But the <input> it's outside the component, of course.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.