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:
2026-07-15 21:11:53 +02:00
parent 3bbc26e5b7
commit 2f5a230370
3 changed files with 85 additions and 24 deletions
@@ -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')
}