Closed pingshunhuangalex closed 7 years ago
Please do not link me, I am just a contributor, no collaborator or maintainer / owner.
Can you provide some codepen with some code which simulates your case? Afaik closing and reopening is the only solution so far (the most simple and direct way).
I'm unsure if removeAutocomplete()
could be of any help. Currently you would have to copy codeparts and execute them in your case to mirror the behavior in the plugin whrn it is closed (blur) and opened (click / focus).
Sorry, I mistake you as a collaborator thanks to your active response in this repository.
At the moment, I'm just using blur
to unfocus and refocus the input, but this causes the dropdown content to flash. The right way to do it is to update things based on the data, so autocomplete doesn't need to be called every time things changes. There should be an updateAutocomplete
feature somehow...
Right. I think we have to improve this and check if data is set and regenerate the list when needed like you describe it.
I could try to check where we have to implement this and which lines are affected later this day.
Or does someone have any recommended fixes and solutions so far?
I can't think of anything at the moment cuz I'm not sure how this is realised in materializeCSS at the moment. I think there should be some kind of an event listener on the data field, so whenever a data change is detected, the list should be updated in real-time.
I'm always curious about where the owner and the collaborators are. It may be better if maintainers all sit down and work something out.
Hi @acburst Just wondering if this issue will be fixed anytime soon? Or it's one of those issues that'll probably never make it to the priority list. Thanks.
Please test https://github.com/Dogfalo/materialize/pull/4725
Just makes sense if the dropdown is already open (you can check if $('.autocomplete-content.dropdown-content')
is not empty).
$(document).ready(function() {
$('input.autocomplete').autocomplete({
data: {
"Apple": null,
"Microsoft": null,
"Google": 'http://placehold.it/250x250'
},
limit: 20, // The max amount of results that can be shown at once. Default: Infinity.
onAutocomplete: function(val) {
// Callback function when value is autcompleted.
},
minLength: 1, // The minimum length of the input for the autocomplete to start. Default: 1.
});
setTimeout(function() {
$('input.autocomplete').autocomplete({
data: {
"Apple": null,
"Microsoft": null,
"Microsoft2": null,
"Microsoft3": null,
"Google": 'http://placehold.it/250x250'
},
limit: 20, // The max amount of results that can be shown at once. Default: Infinity.
onAutocomplete: function(val) {
// Callback function when value is autcompleted.
},
minLength: 1, // The minimum length of the input for the autocomplete to start. Default: 1.
});
$('input.autocomplete').trigger('updateData');
}, 10000);
});
loaded the page, clicked in the input and entered m
, waited for about 10 seconds and the dropdown was updated.
Thanks for the update @DanielRuf Unfortunately, it doesn't quite work there. I mean the data does get updated, but the dropdown list didn't unless I unfocus and refocus.
This means your trigger there doesn't work cuz you can have the same effect just by recalling the entire autocomplete
function, just like what you did above before the trigger.
Well, here it worked. Did you add the code right before the search / keypress method and recompile or directly change the unminified js file?
The dropdown was open and the input focussed and automatically updated itself.
I could also test and integrate some data method (an event with the new data as parameter) if I find the time.
So far the code worked on my side while the input was focused and was open. Maybe I have to check if it is currently opened or not and return / exit if it is not.
I can't test it this weekend. I'll have to test it next week when I get back to work.
Just make sure I get things right. I download the repository from your branch and load the minified JS in the dist folder.
I'm using Vue, so there is no keypress. I run the code whenever there is an input change which should be the same. I also tried it when the page is mounted, and no luck back then. I'll retest it next week.
Another thing is my autocomplete starts when the first letter is input. There is no dropdown when the autocomplete initiated. Will your solution takes care of situation like this?
Thanks again for the updates, if the way I load the file is wrong, please let me know.
Just make sure I get things right. I download the repository from your branch and load the minified JS in the dist folder.
Clone / download the branch f the PR, go to the new directory, run npm install
and then grunt
and use the generated files from dist or bin.
Another thing is my autocomplete starts when the first letter is input. There is no dropdown when the autocomplete initiated. Will your solution takes care of situation like this?
Currently not. A check if the dropdown is populated / shown is not yet implemented.
Hi @DanielRuf
Thanks so much. It works now. Could you please merge it to master
so I can get the feature in cdn instead of a local js file? Thanks.
cc @tomscholz
Also should we improve it and add a check if it is open? I guess so. Will prepare another commit later and push it to the branch. Should work much better.
PS: Imho CDNs are not a good idea anymore. http2, hosting the file yourself and having a fallback when the CDN is not available, extra DNS lookups and requests, SRI, ...
Hi @DanielRuf
Just as a feedback, I noticed sometimes when the update kicks in, the dropdown menu will still blink, which is quite annoying. Hope there is a way around it. Thanks.
@pingshunhuangalex can you share a codepen with your code + the modified dropdown component js from the PR? This would be great.
Do you have more info about your envitonment (browser, OS and so on)?
Hi @DanielRuf Thanks for the reply. I'm on Windows 10 64-bit, and use Chrome 59 and IE 11 for testing.
The blinking happens when none of the dropdown items matches the updated search string. I guess it's just removing ul
and constructing new ones. What I'm asking is: is it possible to keep the ul
and just update the data on it (unless the dropdown item no is smaller than the limit set), so everything just looks consistent.
I can't produce a codepen for testing cuz I probably shouldn't connect it to a server and it's kind of all tangled to other components in a big Vue project. However, I posted my Vue component code related to the search bar below. I put the modified dropdown component js from the PR in this codepen. Thanks.
<template>
<nav>
<div class="nav-wrapper" id="nav-bar">
<div class="input-field" v-show="!expansionMode">
<input id="search"
ref="search"
type="search"
autocomplete="off"
placeholder="Search in Objects Library..." required
v-model="searchTerm"
@keyup.enter.prevent="searchSubmit">
<label class="label-icon" for="search"></label>
<i class="material-icons" @click.prevent="searchSubmit">search</i>
<i class="material-icons" @click="searchClear">close</i>
</div>
</div>
</nav>
</template>
<script>
import mixin from '@/assets/js/mixin';
export default {
name: 'NavSearch',
mixins: [mixin],
data () {
return {
searchTerm: null
};
},
watch: {
searchTerm () {
this.searchUpdate();
}
},
methods: {
searchUpdate () {
let search = this.$refs.search;
axios.get(
`api/v1/search-as-you-type?format=json&query=${this.searchTerm}`
).then(response => {
// console.log(response);
let searchData = response.data.results;
let searchDataObj = {};
let vm = this;
for (let i = 0; i < searchData.length; i++) {
searchDataObj[searchData[i]] = null;
}
$(search).autocomplete({
data: searchDataObj,
limit: 5,
onAutocomplete () {
vm.searchSubmit();
},
minLength: 1,
});
if (search === document.activeElement) {
$(search).trigger('updateData');
} else {
$('.autocomplete-content.dropdown-content').empty();
}
});
}
}
};
</script>
Sounds like we have to cache / store some data to check against it.
is it possible to keep the ul and just update the data
Requires a bit more work and planning. I did not yet have the time to implement this further but I guess this would be related to https://github.com/Dogfalo/materialize/issues/4714#issuecomment-304250161 where I would also check the length of the children and the last value to decide if rerendering is needed and improve the rendering process to inject the new data on the right position as just appending it might not always be the right solution so I would have to diff the old and new data to get the position to inject it without rerendering the whole part.
Ok, I'll try to create a complete codepen with the given code this evening and try to find the fastest solution for you that fixes this issue and update the linked PR (which is still WIP).
@tomscholz any quick solutions that come to your mind? I'll try to revisit the whole code of the component and my PR this evening and extend this.
Probably copying/emulating virtual DOM concepts?
Thanks @DanielRuf No need to rush and there is no deadline.
Again, it's not the speed of the update, it's more like the way it gets updated in the frontend. You can see when you keep adding on letters to a word, it works pretty well because the ul
is not getting destroyed. All I ask is something like that even when the item gets updated, i.e. update the text in ul > li
, not destroying and reconstructing them unless the no. of items is smaller than the user set limit. Thanks.
All I ask is something like that even when the item gets updated, i.e. update the text in ul > li, not destroying and reconstructing them unless the no. of items is smaller than the user set limit. Thanks.
Ah ok, I'll make some thoughts about this and the best approach to tackle this.
Hi @DanielRuf
Just wonder if the updateData feature will be built into the next update (which I have no idea when)? It's ok if you can't figure out the best approach we mentioned above, just wonder at least when that feature will be accesible. Thanks.
This will be added in v1 with the chips rewrite
Added in bf24cb7d
I'm using the
autocomplete dropdown
here to create a search bar with autocomplete feature. The example works fine where thedata
section is static and initialised when the page fires up.However in my case, things are a bit more complicated. I have an api that's feeding me dynamic data when the input content changes. Right now, I'm calling
$().autocomplete
every time the data is updated. Unfortunately using this method, the expanded dropdown list won't update itself accordingly right away unless I unfocus and refocus the search bar.Just wondering if you guys can take a step further and make the
dropdown-content
updates itself whenever the data is changed. Thanks.