Guide on sending an array of objects to Material Vue Autocomplete

Context

Currently, I am dealing with a situation where I am passing an array of objects to a material autocomplete feature. The documentation for this can be found here.

However, upon selecting an item from the list for the first time, it throws an error. Strangely enough, if I click on the item again, it eventually selects it as expected. This strange behavior seems to repeat every time I interact with the autocomplete items.

Error Illustration

[Vue warn]: Error in event handler for "input": "TypeError: Cannot read property 'constructor' of undefined"

Sample Code Snippet

<template>
<md-autocomplete 
  v-model="customer"
  :md-options="customers" 
  @md-changed="getCustomers" 
  @md-opened="getCustomers"
  @md-selected="getSelected" 
>
</md-autocomplete>
</template>

<script>
data: () => ({
    customers: [],
    customer: "", // I also tried making this a {}
 }),
methods: {
getCustomers(searchTerm) {
  this.customers = new Promise(resolve => {
    if (!searchTerm) {
      resolve(this.GET_CUSTOMERS);
    } else {
      const term = searchTerm.toLowerCase();
      this.customers = this.GET_CUSTOMERS.filter(({ email }) => {
      email.toLowerCase().includes(term);
  });
    resolve(this.customers);
  }
  });
},


getSelected() {
     console.log(this.customer);
   },
}
</script>

Data Example

GET_CUSOTMERS: [
  { client_id: 1, email: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="73160b121e031f1633160b121e031f165d101c1e">[email protected]</a>" },
  { client_id: 2, email: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="67021f060a170b0227021f060a170b024904080a">[email protected]</a>" }
];

Inquiry

I'm currently facing an error message and would like some advice on how to fix it. Does anyone know what this error indicates? I've heard about similar bugs in Angular's autocomplete feature using Material, but I believe there might be a solution specific to Vue Material. Your insights are greatly appreciated.

Answer №1

Troubleshooting the issue at hand

Upon analyzing the source code of MdAutocomplete's input-handler, it appears that in your scenario, searchTerm is undefined, leading to the error related to accessing the constructor of undefined:

// MdAutocomplete.vue: onInput()
if (this.searchTerm.constructor.toString().match(/function (\w*)/)[1].toLowerCase() !== 'inputevent') {
         ^^^^^^^^^^

In normal circumstances, searchTerm should be equivalent to its value prop:

data () {
  return {
    searchTerm: this.value,
    //...
  }
},
watch: {
  value (val) {
    this.searchTerm = val
  },
  //...
},

...unless an item is selected:

selectItem (item, $event) {
  const content = $event.target.textContent.trim()
  this.searchTerm = content
  //...
}

Therefore, when encountering the error, it's probable that the value attribute of MdAutocomplete is somehow undefined (from your v-model), causing searchTerm to also become undefined. Upon selecting an item, the searchTerm resets to the text content of the selection, resolving the error.

Although I couldn't replicate those precise symptoms with the provided code snippet, unrelated errors emerged: demo. It's plausible that essential details are missing from the question for problem reproduction purposes.

Utilizing an object array for md-autocomplete options

  • The md-options (in this case, this.customers) promise ought to yield an array of strings, necessitating conversion of your object array into the anticipated format by employing Array.prototype.map):

    this.customers = new Promise(resolve => {
      if (!searchTerm) {
        resolve(GET_CUSTOMERS.map(x => x.email));   // <-- mapping to `email` property
      } else {
        const term = searchTerm.toLowerCase();
        this.customers = GET_CUSTOMERS.filter(/*...*/).map(x => x.email);   // <-- mapping to `email` property
        resolve(this.customers);
      }
    }
    
  • The callback utilized for Array.prototype.filter needs to output a Boolean for filtering to take effect. The following arrow function, used as the callback, returns nothing:

    GET_CUSTOMERS.filter(({ email }) => {
      email.toLowerCase().includes(term);
    });
    

    You can either eliminate the brackets within the arrow function:

    GET_CUSTOMERS.filter(({ email }) => email.toLowerCase().includes(term));
    

    or incorporate a return statement:

    GET_CUSTOMERS.filter(({ email }) => {
      return email.toLowerCase().includes(term);
    });
    

Demo showcasing the fix

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to organize data by month using Chart Js?

I have been working with Chart.js and encountered an issue while trying to organize the dates fetched from my MongoDB to display them according to the respective month. In the provided image, the line does not seem to align with the correct month index. I ...

Utilizing the document.createDocumentFragment() method along with innerHTML for manipulating a Document Object Model (

I am currently in the process of creating a document fragment using the code below: let fullHTMLDocument = '<!doctype html> <html><head></head><body><h1>hello world</h1></body></html>'; let f ...

What could be causing my HTML5 video control buttons to not function properly when using JavaScript?

I am currently working on a project that involves integrating external HTML buttons with a <video> element to control playback functions such as play/pause, rewind slow, rewind fast, and fast forward using JavaScript. Although I have successfully pos ...

Can you explain the significance of the symbol '#' in a Vue Router URL?

I am wondering about the significance of the hash in Vue Router URL. I have noticed that by using mode: 'history', I can eliminate it from the URL. What are the practical differences between having the hash and not having it? ...

Tips for accurately determining the byte count of text within a TextArea

I am trying to figure out how to accurately calculate the byte size of text within a specific textarea. Although I have access to .Net libraries, I am looking for a Javascript solution instead. How many bytes does each character represent? What is the most ...

When it comes to HTML and Javascript drawing, getting the positioning just right can be a challenge

I'm currently developing a control website for a drawing robot as part of a school project. However, I've been facing some challenges with the functionality of the drawing feature. Though I admit that the site lacks attention to detail, my main ...

What are some ways to implement smooth scrolling when a navigation link is clicked?

I have a total of 3 links in my navigation bar and every time they are clicked, I want the page to smoothly scroll down to their designated section on the webpage. Although I have already set up the anchors, I lack experience in scripting to create the smo ...

Having trouble accessing a React component class from a different component class

I just started learning reactjs and javascript. For a simple project, I'm working on creating a login and registration form. The issue I'm facing is that when a user enters their email and password and clicks 'register', instead of movi ...

A Guide to Effortlessly Implementing moment.js into a React TypeScript Application

I'm attempting to implement code splitting and one of the specific packages I want to separate into its own chunk is moment.js. Here's how I'm doing it: const myFunc = async (currentNumber) => { const moment = (await import('momen ...

Angular ngx-translate not displaying image

My Angular application is utilizing ngx-translate to support multiple languages. I am trying to dynamically change an image based on the language selected by the user. However, I am facing difficulty in updating the image when a language is clicked. The ap ...

Changing all object values to true with React useState

In a certain file, I have defined an object with the following structure: export const items = { first: false, second: false, third: false } Within a component, I am using this object as shown below: import { items } from 'file'; const [el ...

What is the best way to generate a live map with constantly updating markers?

Is it possible for me to learn how to develop a live map similar to the one on this site: www.lightningmaps.org? It's fascinating to watch new markers pop up every few seconds. I'm interested in building a real-time map that can track IP locatio ...

Using AngularJS and the ng-show directive, you can set a <div> element to

Objective: My aim is to show the content of a div according to the status of checkboxes, while also ensuring that these divs are visible by default If I have this code snippet: <html> <head> <script src="https://ajax.googleapis.com/ajax/li ...

Tips on connecting data within a jQuery element to a table of data

I am currently developing a program that involves searching the source code to list out element names and their corresponding IDs. Instead of displaying this information in alert popups, I would like to present it neatly within a data table. <script> ...

Adding elements to list items

Here is some HTML code that I am working with: <div> <ul id="one"></ul> </div> I also have this code snippet for appending a li element to the ul: $("#one").append("<li id='libtn2630275Chat'><img id=' ...

Map does not provide zero padding for strings, whereas forEach does

Currently working on developing crypto tools, I encountered an issue while attempting to utilize the map function to reduce characters into a string. Strangely enough, one function works perfectly fine, while the other fails to 0 pad the string. What could ...

The functionality to remove table rows when checkboxes are selected is not functioning as expected in an Angular 7 application

My table contains data generated from a loop. When I click the edit button, additional buttons and textboxes are enabled. If multiple checkboxes are checked, the add buttons become disabled. However, if all checkboxes except one are unchecked, the add bu ...

Incorporate a versatile navigation menu into your HTML pages

At the moment, my website is built with static hand-coded HTML pages. I manually add a navigation menu to each page individually. However, I am looking for a more efficient way to manage this process by maintaining a single user resource file that contains ...

Utilizing Ajax for Efficiently Updating a Singular Field within a Designated Object

How can I use Ajax to Update a Single Field in a Specific Object? I have a table in my postgres database with numerous records. I am interested in using a jquery Ajax request to update just one field in a particular object within that table. Is it possibl ...

Ensure Angular JS includes a space or special character after applying a currency filter

Is there a way to include a space or special character after the "₹" symbol? Desired output: ₹ 49 Current output: ₹49 HTML - {{cart.getTotalPrice() | currency:"₹"}} ...