SearchForm: fix inconsistent/mixed search results
- SearchForm.vue: route Enter key through submit() (native form submit interception) so it behaves like the button; fix autocomplete array mutation during iteration in the typed watcher. - Base.vue: parse terms consistently in beforeRouteUpdate; render items via displayedItems (drops sparse holes); only mount infinite-loading after the first page and reset it per search via :identifier. - search store: guard against stale async responses (searchId); place each page at its offset instead of concatenating in arrival order, which mixed pages when a later page resolved first.
This commit is contained in:
@@ -135,16 +135,17 @@ export default {
|
||||
// let tag_list = n
|
||||
// }
|
||||
// remove terms from autocomplete if removed from typed
|
||||
if (typeof n !== 'string') {
|
||||
return
|
||||
}
|
||||
const r = /,\s?$/ // remove last comma space
|
||||
let tag_list = n.replace(r,'').split(', ')
|
||||
console.log('watch typed tag_list', tag_list)
|
||||
console.log('watch typed autocomplete before', this.autocomplete)
|
||||
this.autocomplete.forEach( (term,index,array) => {
|
||||
console.log("watch typed autocomplete term", term, index, array)
|
||||
if (tag_list.indexOf(term.label) < 0) {
|
||||
this.autocomplete.splice(index,1)
|
||||
}
|
||||
});
|
||||
// Keep only the terms whose label is still present in the typed text.
|
||||
// Filtering into a new array avoids skipping items when splicing during
|
||||
// iteration (which left stale terms in autocomplete, corrupting `terms`).
|
||||
this.autocomplete = this.autocomplete.filter(term => tag_list.indexOf(term.label) >= 0)
|
||||
console.log('watch typed autocomplete after', this.autocomplete)
|
||||
},
|
||||
keys(n, o){
|
||||
@@ -166,6 +167,20 @@ export default {
|
||||
mounted(){
|
||||
// console.log('SearchForm mounted')
|
||||
Drupal.attachBehaviors(this.$el);
|
||||
|
||||
// Route the native form submission (Enter key) through the same submit()
|
||||
// method as the button (@click.prevent="submit"). Without this, pressing
|
||||
// Enter either triggers a native POST reload or only fills the jQuery UI
|
||||
// autocomplete selection, so keys/terms sent to the backend differ from a
|
||||
// button click and the search results are inconsistent.
|
||||
// Note: when the autocomplete menu is open, jQuery UI handles Enter itself
|
||||
// (selects the highlighted suggestion) and prevents this submit event, which
|
||||
// is the intended behaviour.
|
||||
this.$el.addEventListener('submit', (e) => {
|
||||
e.preventDefault()
|
||||
this.submit()
|
||||
})
|
||||
|
||||
// get the search input
|
||||
this.$input = this.$el.querySelector('#edit-search')
|
||||
// // focus on input
|
||||
|
||||
@@ -11,13 +11,14 @@
|
||||
<span>{{ $t('default.Loading…') }}</span>
|
||||
</div>
|
||||
<ul v-else>
|
||||
<li v-for="item in items" v-bind:key="item.id">
|
||||
<li v-for="item in displayedItems" v-bind:key="item.id">
|
||||
<Card v-if="item.bundle == 'materiau'" :item="item"/>
|
||||
<CardThematique v-if="item.bundle == 'thematique'" :item="item"/>
|
||||
</li>
|
||||
</ul>
|
||||
<infinite-loading
|
||||
v-if="count > limit"
|
||||
v-if="count > limit && displayedItems.length >= limit"
|
||||
:identifier="searchId"
|
||||
@infinite="nextPage"
|
||||
>
|
||||
<div slot="no-more">No more results</div>
|
||||
@@ -48,8 +49,14 @@ export default {
|
||||
searchinfos: state => state.Search.infos,
|
||||
count: state => state.Search.count,
|
||||
noresults: state => state.Search.noresults,
|
||||
limit: state => state.Search.limit
|
||||
})
|
||||
limit: state => state.Search.limit,
|
||||
searchId: state => state.Search.searchId
|
||||
}),
|
||||
// items is a sparse array (pages placed by offset); drop the holes left by
|
||||
// pages that returned fewer results than the limit before rendering.
|
||||
displayedItems () {
|
||||
return this.items.filter(Boolean)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
@@ -98,7 +105,10 @@ export default {
|
||||
// todo text field of search form is not emptying on clicking on base after a search
|
||||
// this.$store.commit('Search/setKeys', to.query.keys)
|
||||
if (to.query.hasOwnProperty('terms')) {
|
||||
this.$store.commit('Search/setTerms', to.query.terms)
|
||||
// to.query.terms is a raw JSON string (see SearchForm.submit) and must be
|
||||
// parsed like in created(), otherwise getResults() double-encodes it and
|
||||
// the backend silently drops the terms (less relevant results).
|
||||
this.$store.commit('Search/setTerms', JSON.parse(to.query.terms))
|
||||
}else{
|
||||
this.$store.commit('Search/reSetTerms')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user