Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mdAutocomplete] Error in nextTick: "Error: You should use a fetch function prop" #1002

Closed
alexMugen opened this issue Aug 25, 2017 · 23 comments

Comments

@alexMugen
Copy link

Hello,

i want to use md autocomplete, with list prop and filteredList but i have an error

Error in nextTick: "Error: You should use a fetch function prop"

my code below :
<md-autocomplete :min-chars="3" v-model="searchAgenciesQuery" :list="agencies" :filter-list="filteredAgencies" ">

agencies is the result of my promise

Services.getAgencies({size: 1000, page: 0}).then(resp => {
        this.agencies = resp
      })

filteredAgencies is my filter method :

filteredAgencies () {
        let query = this.searchAgenciesQuery
        if (query) {
          return this.agencies.filter(agency => {
            let filterByName = agency.name ? agency.name.toLowerCase().includes(query.toLowCase()) : ''
            let filterById = agency.id !== null ? agency.id.includes(query) : ''
            return filterByName || filterById
          })
        }
      }

I don't understand the difference between list prop and fetch prop. I don't use fetch cuz i have to store locally my agencies, so my promise is not for the fetch that it should return but it implement on the created, so i dont want to use fetch way

 created () {
      Services.getAgencies({size: 1000, page: 0}).then(resp => {
        this.agencies = resp
      })
    },

Thanks a lot for your help

@alexMugen alexMugen changed the title Md autocomplete Error in nextTick: "Error: You should use a fetch function prop" [mdAutocomplete] Error in nextTick: "Error: You should use a fetch function prop" Aug 25, 2017
@alexMugen
Copy link
Author

alexMugen commented Aug 25, 2017

i tried with fetch prop and i have

this.fetch(...).then is not a function

my code :

<md-autocomplete :min-chars="3" v-model="searchAgenciesQuery" :fetch="filteredAgencies"></md-autocomplete>

methods: {
      filteredAgencies (param) {
        let query = param.q
        let filtered = this.agencies.filter(agency => {
          let filterByName = agency.name ? agency.name.toLowerCase().includes(query.toLowerCase()) : ''
          let filterByRegion = agency.address.region ? agency.address.region.toLowerCase().includes(query.toLowerCase()) : ''
          let filterById = agency.id !== null ? agency.id.includes(query) : ''
          return filterByName || filterById || filterByRegion
        })
        return query.length >= 1 ? filtered : this.agencies
      }
    }

@VdustR
Copy link
Member

VdustR commented Aug 25, 2017

I wrote an example for you.

filter-list: Yous should pass a function.

{
  methods:{
    filterList: (list, inputString) => {
      // do some thing
      return result
    }
  }
}

fetch: You should return a promise in your fetch method or declare it as an async function.

{
  methods:{
    fetch: async ({q}) => {
      let inputString = q
      let result = await getResult(inputString)
      return result
    }
  }
}

Use list and filter props if you don't need to do an async method (like ajax) to get the result,
or use fetch props if you have to.

It's more likely better to use list and filter props than fetch in your case that you only fetch the list once on component created.

@alexMugen
Copy link
Author

Hello,

Thank you for your helping !
I understand now difference between differents props list and fetch but i cannot use it but I'm sorry i can't make it works, i have this error

You should use a filterList function prop with the list prop

methods: {
      filteredAgencies: (agencies = this.agencies, query = this.searchAgenciesQuery) => {
        return agencies.filter(agency => {
          let filterByName = agency.name ? agency.name.toLowerCase().includes(query.toLowerCase()) : ''
          let filterByRegion = agency.address.region ? agency.address.region.toLowerCase().includes(query.toLowerCase()) : ''
          let filterById = agency.id !== null ? agency.id.includes(query) : ''
          return filterByName || filterById || filterByRegion
        })
      }
    }

I pass anonymous method to filteredAgencies and my html is the same as before:
<md-autocomplete :min-chars="3" v-model="searchAgenciesQuery" :list="agencies" :filter-list="filteredAgencies"></md-autocomplete>

@VdustR
Copy link
Member

VdustR commented Aug 28, 2017

What error did you got?

Could you please reproduce it in codepen?

@alexMugen
Copy link
Author

alexMugen commented Aug 28, 2017

i simplify some code (i mocked calls instead of calling service get etc.. ) but the logic is the same
thank you !
my error :

[Vue warn]: Error in nextTick: 'Error: You should use a filterList function prop with the list prop'

`

See the Pen Vue Material Issue #1002 by Alex (@Alex_Mugen) on CodePen.

<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>`

@alexMugen
Copy link
Author

alexMugen commented Aug 28, 2017

oups , i changed version of dependencies now it's work on codepen , i set the last version of vuejs and vue material as my package json in my project :

"vue": "^2.3.3",
    "vue-material": "^0.7.1"

But in my project it still not works it shows error

You should use a filterList function prop with the list prop

and when i try to write some text in my input

Cannot read property 'focus' of undefined

Cannot read property 'value' of undefined

is it possible it is a version problem ? because i try with my first version of my code as above and it works.. But it looks strange because in my package json i tell to get the last version started from ***

"vue": "^2.3.3",
    "vue-material": "^0.7.1"

@VdustR
Copy link
Member

VdustR commented Aug 28, 2017

[Vue warn]: Avoid using non-primitive value as key, use string/number value instead.

e.g.
```javascript
{
  data () {
    return {
      list: ['str1', 'str2', 'str3']
    }
  }
}
```

You put objects in list array.

Thus, the key of the menu is the agency objects. That cause this warning.

~~~It's better to computed a distinct string array list from the original list to pass as `:list`~~~

~~~Autocomplete component is a helper for a string, not a selecter for an object.~~~


updated: [#issuecomment-325378263](#issuecomment-325378263)

@alexMugen
Copy link
Author

thank you for your explanation for

[Vue warn]: Avoid using non-primitive value as key, use string/number value instead.

I tried differents solutions but i cannot find the right , i have again

vue.esm.js?65d7:566 Error: You should use a filterList function prop with the list prop

while on the copen it works

@VdustR
Copy link
Member

VdustR commented Aug 28, 2017

I cannot help you if you don't reproduce it.

@VdustR
Copy link
Member

VdustR commented Aug 28, 2017

I misunderstood about the warning:

[Vue warn]: Avoid using non-primitive value as key, use string/number value instead.

I check the code b802afd mdAutocomplete line 26

That list should be an object list so it's seem like the warning always happen. I think it's an issue.

You could decide what property key to show or select by the :print-attribute, which default is name.

@alexMugen
Copy link
Author

alexMugen commented Aug 28, 2017

ok thank you for the precision 🥇

i'm trying to understand my bug with

Error: You should use a filterList function prop with the list prop

@alexMugen
Copy link
Author

alexMugen commented Aug 28, 2017

I cannot understand the mistake..
https://codepen.io/Alex_Mugen/pen/wqYJew?editors=1011 i copy paste the same from my webpack project to my codepen ( expect method get that calling service but even if i mockup agencies with array static it doesn't work ) and it works on codepen only

In my project ,

i have a template :
<md-autocomplete :min-chars="3" v-model="searchAgenciesQuery" :list="agencies" :filter-list="filteredAgencies"></md-autocomplete>

i have a created that get agencies :

Services.getAgencies({size: 1000, page: 0}).then(resp => {
        this.agencies = resp
      })

I have a methods that contains filteredAgencies :

filteredAgencies () {
        console.log('filteredAgencies')
        return this.agencies.filter(agency => {
          let filterByName = agency.name ? agency.name.toLowerCase().includes(this.searchAgenciesQuery.toLowerCase()) : ''
          let filterByRegion = agency.address.region ? agency.address.region.toLowerCase().includes(this.searchAgenciesQuery.toLowerCase()) : ''
          let filterById = agency.id !== null ? agency.id.includes(this.searchAgenciesQuery) : ''
          return this.searchAgenciesQuery.length > 1 ? filterByName || filterById || filterByRegion : this.agencies
        })
      },

and that 's all ...
🆘

@VdustR
Copy link
Member

VdustR commented Aug 28, 2017

Did you upgrade the modules to latest version?

@alexMugen
Copy link
Author

i think is already the latest version because in my package json i have
"vue": "^2.3.3", "vue-material": "^0.7.1"

It means that it take the latest right ?

@VdustR
Copy link
Member

VdustR commented Aug 29, 2017

Execute this command in your project directory to check modules installed

npm ls --depth=0

@alexMugen
Copy link
Author

alexMugen commented Aug 29, 2017

Thank you !
It looks like ok for latest version

vue@2.4.2
├── vue-loader@12.2.2
├── vue-material@0.7.4
├── vue-router@2.7.0
├── vue-style-loader@3.0.1
├── vue-template-compiler@2.4.2
├── webpack@2.7.0
├── webpack-bundle-analyzer@2.9.0
├── webpack-dev-middleware@1.12.0
├── webpack-hot-middleware@2.18.2
└── webpack-merge@4.1.0

🤔

@alexMugen
Copy link
Author

alexMugen commented Aug 29, 2017

i compared two code again and it's exaclty the same, i set my agencies as a local array like in code pen because it s the only difference but it doesn't work 👿

@alexMugen
Copy link
Author

Sorry i missed something ,

i tested to set a local array like this :

Services.getAgencies({size: 1000, page: 0}).then(resp => {
        this.agencies = [{name:'toto', region: 'test', id: '123'},
                     {name:'tata', region: 'aze', id: '456'},
                     {name:'titi', region: 'taiwan', id: '789'}]
      })

instead of set agencies without promise

this.agencies = [{name:'toto', region: 'test', id: '123'},
                     {name:'tata', region: 'aze', id: '456'},
                     {name:'titi', region: 'taiwan', id: '789'}]

now i have the error we talked before

[Vue warn]: Avoid using non-primitive value as key, use string/number value instead.

@VdustR
Copy link
Member

VdustR commented Aug 29, 2017

It's not a fatal error. I think you could ignore it temporarily.

I have no idea whether this change with the key of the menu item is a good idea or not:

<md-menu-item v-if="items.length"
  v-for="item in items"
  :key="item[printAttribute]"
  @keyup.enter="hit(item)"
  @click="hit(item)">
  {{ item[printAttribute] }}
</md-menu-item>

@alexMugen
Copy link
Author

ok , i will use md-autocomplete if it'ss not a fatal error !

i want to say you thank you a lot 🥇

@SergioReis97
Copy link

SergioReis97 commented Sep 15, 2017

Kept getting the error

You should use a filterList function prop with the list prop

Tinkered around and got it to work like this

<md-input-container>
   <label class="specialSelect">AutoComplete</label>
   <md-autocomplete name="autoComplete" id="autoComplete" :filterList="someFunction" :min-chars="0" :list="[{name:''}]"  v-model="myModel"></md-autocomplete>
   <md-button v-if="myModel" @click="myModel = '' " class="md-icon-button">
      <md-icon>clear</md-icon>
   </md-button>
</md-input-container>

.
.
.

methods:{
    someFunction() {
      // TODO actual filtering
      return this.myList;
    },
    getFunctionThatIsCalledOnCreate(){
          this.$http.get(url, {}).then((response) => {
        var result = response.data;
        if (this.myList != result.myListFromServer) {
          var outputList = [];
          for (var k in result.myListFromServer) {
           // Pretty sure there are better and easier ways of doing this (converting string array to object array with a prop)
            var line = result.myListFromServer[k];
            outputList.push({ name: line });            
          }
          if (outputList != null && outputList != [])
            this.myList = outputList;
        }
      })
   }
}

Using name since its default but can be changed in 'print-attribute' prop

@Samuell1
Copy link
Member

Closing this issue as our focus is on the new 1.0.0 version.

@fpinzn
Copy link

fpinzn commented Dec 15, 2017

In case anyone is using the 0.8.1 version and gets this error. It happens when the initial state of the list you're pointing to is empty. Simply initialize the list with fake data. Something like:

list= [{name: 'loading', id: -1}]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants