Dogfalo / materialize

Materialize, a CSS Framework based on Material Design
https://materializecss.com
MIT License
38.86k stars 4.74k forks source link

Function to update autocomplete data for chips #6401

Closed JanieHuang closed 5 years ago

JanieHuang commented 5 years ago

Hi all,

There is a way to update autcomplete data on M.Autocomplete through calling instance.updateData(data), but there's no way I can see to do this on M.Chips.

What I'm trying to do, is have an input that takes chips with autocomplete on.

When a user wants to add a custom tag, all they do is type the name and add it. This will then add it to the autocomplete options for the user to pick from again.

For example, if I type in "Mozilla", no autocomplete options should appear as it is a custom tag. When I hit enter and it is added as a chip, it is now a new tag added to the autcomplete option. If I begin to type "M", "Mozilla" should now appear on the dropdown as an option.

I was trying to add the updated options list to onAddChip, however I can't seem to update the autcomplete list to reflect those changes, and there's not function I can call to "refresh" it either.

Is there any way to implement this? Or am I going about it the wrong way and it should be achievable in it's current state?

JsFiddle with the skeleton of what I'm trying to achieve

cdn versions linked:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">

<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>

JanieHuang commented 5 years ago

Figured it out, it actually does work as intended, and it does use the same autocomplete as implemented previously, meaning it does have an "updateData" function.

For anyone wishing to know how to dynamically add and remove options after a chip is added. My problem was I was not adding the object correctly to options after the chip was added.

To refer to it inside the chip instance, it is: this.autocomplete.updateData(options);

Or using the materialize documentation:

this.autocomplete.updateData({
  "Apple": null,
  "Microsoft": null,
  "Google": 'https://placehold.it/250x250'
});

Here's the full updated code:

Setup

//Initialize component
M.AutoInit();

//Select elements
var elems = document.querySelectorAll(".chips");

//Dummy array 1 with data
// ** MUST BE IN THIS FORMAT OR WILL NOT CONVERT PROPERLY **
var tempArray = new Array();
tempArray['Apple'] = null;
tempArray['Oranges'] = null;
tempArray['Google'] = null;
tempArray['Microsoft'] = null;

//convert array into an object 
// ** ALSO MUST BE DONE **
var options = Object.assign({}, tempArray);

Instance creation, here's where the main part is

//Create instance
var instances = M.Chips.init(elems, {
  autocompleteOptions: {
    data: options //Set autocomplete options
  },
  onChipAdd: function(e, chip) {

    //ON chip add, as long as chip is not empty
    if (chip.innerText !== undefined) {

      //Parse out the "close" that gets added onto the chip
      // ** MUST TRIM FOR SPACES **
      var lastIndex = chip.innerText.lastIndexOf("close");
      var parsedText = chip.innerText.substring(0, lastIndex).trim();

      //Set the new chip in the array
      tempArray[parsedText] = null;

      //Reconvert the array to an object
      options = Object.assign({}, tempArray);

      //Update the chips autocomplete to the new options
      this.autocomplete.updateData(options);
    }
  },

  onChipDelete: function(e, chip) {

    //Similar to adding chip
    //As long as chip is not empty
    if (chip.innerText !== undefined) {

      //Parse out chip's close and extra spaces
      var lastIndex = chip.innerText.lastIndexOf("close");
      var parsedText = chip.innerText.substring(0, lastIndex).trim();

      //Delete the object in the array
      delete tempArray[parsedText];

      //Reconver tthe array 
      options = Object.assign({}, tempArray);

      // or swap with a completely new array
      // options = Object.assign({}, tempArray2);

      //Update the autocomplete options
      this.autocomplete.updateData(options);

    }

  }
});