Geoff_S
Geoff_S

Reputation: 5107

Vue autocomplete in laravel

I'm working on an issue with a vue autocomplete function in a laravel site.

I've set my route, controller and blade. Currently, if I inspect the vue component and type in the input, it shows the keywords I'm typing in the console, so I know it's catching what I'm typing.

As for the $groupResult in my controller, if I just dump that on my page then it dumps about 100 results as expected. All I want to do is have an autocomplete on the input that searches within those 100 results.

What exactly am I missing here?

Route

Route::get('campaigns/categories','CampaignsController@searchcategories')->name('campaigns.categories');

Controller:

public function searchcategories(Request $request)
{
    $userNum = $this->user;
    $category = new categoryService();
    $safecategories = $category->info($userNum);

    $groupResult = array();

    foreach($safecategories->categories as $categories){
        $groupItem = array();
        $groupItem["group_code"] = $categories->group_code;
        $groupItem["group_name"] = $categories->group_name;

        array_push($groupResult, $groupItem);
    }

     return view('campaigns')
        ->with('groupResult', $groupResult);

}

Blade

<div id="categoryNames">
<input type="text" v-model="keywords">
<ul v-if="results.length > 0">
  <li v-for="result in results" :key="result.id" v-text="result.name"></li>
</ul>
</div>

var categoryNames = new Vue({
  data() {
    return {
      keywords: null,
      results: []
    };
  },

  watch: {
    keywords(after, before) {
      this.fetch();
    }
  },

  methods: {
    fetch() {
      axios.get('campaigns/categories', { params: { keywords: this.keywords } })
        .then(response => this.results = response.data)
        .catch(error => {});
    }
  }
}).$mount('#categoryNames');

Upvotes: 0

Views: 2019

Answers (1)

Tim Wickstrom
Tim Wickstrom

Reputation: 5701

If you're simply attempting to filter the existing results there is no need to call the server to do this.

<div id="categoryNames">
<input type="text" v-model="keywords">
<ul v-if="filteredResults.length > 0">
  <li v-for="result in filteredResults" :key="result.id" v-text="result.name"></li>
</ul>
</div>

var categoryNames = new Vue({
  data() {
    return {
      keywords: null,
      results: []
    };
  },

  computed: {
    filteredResults () {
      return this.keywords ? this.results.filter(row => row.name.search(new RegExp(`${this.keywords}`, 'i')) !== -1) : this.results
    }
  }
}).$mount('#categoryNames');

The computed property returns an array of objects (I assumed you are filtering on the object key name). If a keyword is present it uses regex to perform a case insensitive search. If keyword is not present it returns the full results object.

Note, I did not test this code directly so there may be a typo etc. But have implemented many versions of this in a large scale application.

Upvotes: 1

Related Questions