Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When adding async data to the combobox, the scroll jumps to the top. #2785

Closed
juanjinario opened this issue Oct 4, 2023 · 4 comments
Closed

Comments

@juanjinario
Copy link

I want to have an infinite scroll functionality with the combobox, and when reaching the bottom, I want to add new data. However, this doesn't work because the scroll jumps to the top.

What package within Headless UI are you using?
@headlessui/vue

What version of that package are you using?
1.7.16

What browser are you using?
Chrome

Reproduction URL
The issue can be reproduced by loading the initial data from an endpoint and adding new data while scrolling. It jumps to the top, which doesn't make sense; it should keep the scroll in its current position and add the new elements. If I change the ComboboxOption to a div, the behavior is correct (But I lose other functionalities of the Combobox).

Describe your issue
My code is the following.

<Scroll v-else class="w-full h-40" @next="onNextPage">
	<ComboboxOption
		v-for="item in projectList."
		:key="item.id"
		v-slot="{ selected }"
		:value="item"
		as="template"
	>
		<li
			:class="[
				selected ? 'bg-aux-100 text-aux-300' : 'text-gray-900',
				'relative cursor-default select-none rounded-full py-2 px-4',
			]"
		>
			<span
				:class="[
					selected ? 'font-medium' : 'font-normal',
					'block truncate text-sm',
				]"
			>
				{{ item.name }}
			</span>
			<span
				v-if="selected"
				class="absolute inset-y-0 right-4 flex items-center pl-3 text-aux-300"
			>
				<Icon
					name="icon-check"
					class="h-5 w-5"
					aria-hidden="true"
				/>
			</span>
		</li>
	</ComboboxOption>
</Scroll>

const onNextPage = () => {
      console.log('bottom scroll')
      const { currentPage, lastPage } = projectRequestMeta.value
      if (currentPage < lastPage) {
	      getProjectList({ page: currentPage + 1 })
      }
 }
      
 const getProjectList = async ({ page = 1 }) => {
      try {
	      const { data, meta } = await Project.paginate({
		      query: { page, search: query.value, limit: 30 },
	      })
	      if (page === 1) {
		      projectList.value = []
	      }
      
	      // HERE THE SCROLL RETURN TO TOP
	      projectList.value = [...projectList.value, ...data]
	      // I TRYED WITH projectList.value.push(...data)
	      projectRequestMeta.value = meta
      } catch (error) {
	      handleError(error)
      }
}
@thecrypticace
Copy link
Contributor

@juanjinario Is <Scroll> a virtual scroller component? If so, those are currently incompatible with the release version of Combobox. However, We've done a lot of work recently on experimental virtual scrolling support in our insiders build. I'd suggest you play with the API from this PR using the insiders build and see if it works for you: #2779

@thecrypticace
Copy link
Contributor

Hey, gonna close this for now but one thing you could do if you still experience this is use the by prop on <Combobox> so values are compared by ID rather than the whole object. For example:

<Combobox by="id" … other props here…>
…
</Combobox>

@juanjinario
Copy link
Author

Thanks, I going to test, but I can not understand how it works (by id)

@thecrypticace
Copy link
Contributor

Internally, the combobox uses the entire object passed to :value via ComboboxOption. This can cause problems comparing selected values if you clone or re-create objects in the array. When using by="id" this tells the combobox that the only thing that should be compared is the id key in the object rather than the whole object itself.

This is discussed more in the documentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants