primefaces / primefaces/primereact
Virtual scroll bar not working as expected
Open
Nobody has claimed this yet.
Status: Needs Triage
- Dominant language
- CSS
- Stars
- 8.3k
- Forks
- 1.2k
- PR merge metrics
- No merged PRs in 30d
Description
The virtiual scroll bar is failing to adopt to my styles its only working when i apply card
if i dont put class card it gets hidden i se nothing rendered
// <div className="flex-1 overflow-hidden">
<div className="card flex justify-content-center">
<VirtualScroller
items={agentsData}
itemSize={80}
itemTemplate={agentItemTemplate}
// className="h-full"
// style={{ height: '100%' }}
// className="border-1 surface-border border-round"
// style={{ width: '200px', height: '200px' }}
/>
</div>
here is my full code
'use client'
import React, { useState } from "react";
import { Card } from "primereact/card";
import { Button } from "primereact/button";
import { InputText } from "primereact/inputtext";
import { VirtualScroller, VirtualScrollerTemplateOptions } from 'primereact/virtualscroller';
import { useInfiniteQuery } from "@tanstack/react-query";
import { ProgressSpinner } from "primereact/progressspinner";
import MaterialUiLoaderLottie from "@/assets/nice-lotties/material-ui-loading-lottie.json";
import SnailErrorLottie from "@/assets/nice-lotties/snail-error-lottie.json";
// import SateLiteLottie from "@/assets/nice-lotties/satelite-loading-lottie.json";
// import FileLoadingLottie from "@/assets/nice-lotties/FileLoadingLottie.json";
import SkeletonLoadingLottie from "@/assets/nice-lotties/SkeletonLoadingLottie.json";
import NoDataLottie from "@/assets/nice-lotties/nodata.json";
import { getAllAgents } from "@/services/agents/agents-service";
import useHandleQueryError from "@/hooks/useHandleQueryError";
import dynamic from "next/dynamic";
const Lottie = dynamic(() => import("lottie-react"), { ssr: false });
interface Agent {
id: number;
name: string;
code?: string;
email?: string;
phone?: string;
status?: string;
created_at?: string;
}
function UserAgentsListing() {
const [globalSearch, setGlobalSearch] = useState("");
const [globalSearchTerm, setGlobalSearchTerm] = useState("");
// Fetch Agents data using useInfiniteQuery
const { data, error, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage, status, } = useInfiniteQuery({
queryKey: ["user-agents", "paginate", globalSearchTerm],
queryFn: ({ pageParam = 1 }) => getAllAgents({ page: pageParam, search: globalSearchTerm, paginate: true }),
getNextPageParam: (queryData) => {
console.log("🚀 ~ UserAgentsListing ~ queryData:", queryData);
const pageData = queryData?.data?.data;
return pageData?.current_page < pageData?.last_page ? pageData.current_page + 1 : undefined;
},
initialPageParam: 1,
});
const isError = status === "error";
const isPending = status === "pending";
useHandleQueryError({ isError, error });
// Flatten the paginated data
const agentsData = data?.pages?.flatMap(page => page?.data?.data?.data) || [];
// Search function
const handleSearch = () => {
setGlobalSearchTerm(globalSearch);
};
// Agent item template for VirtualScroller
const agentItemTemplate = (agent: Agent, options: VirtualScrollerTemplateOptions) => {
return (
<div className="border-b border-gray-200 dark:border-gray-700 p-3 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
<div className="flex items-start justify-between gap-3">
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2 mb-1">
<h4 className="text-sm font-semibold text-gray-800 dark:text-white truncate">
{agent.name}
</h4>
{agent.code && (
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-100">
{agent.code}
</span>
)}
</div>
{agent.email && (
<p className="text-xs text-gray-600 dark:text-gray-400 truncate">
📧 {agent.email}
</p>
)}
{agent.phone && (
<p className="text-xs text-gray-600 dark:text-gray-400 truncate">
📱 {agent.phone}
</p>
)}
</div>
{agent.status && (
<span className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium flex-shrink-0 ${agent.status === 'active'
? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-100'
: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-100'
}`}>
{agent.status}
</span>
)}
</div>
</div>
);
};
return (
<div className="h-full">
{isError ? (
<div className="flex justify-center items-center h-full">
<div className="max-w-xs">
<Lottie animationData={SnailErrorLottie} loop autoplay />
</div>
</div>
) : (
<div className="h-full flex flex-col">
{/* Search Box */}
<div className="p-3 border-b border-gray-200 dark:border-gray-700">
<div className="p-inputgroup">
<InputText
type="search"
value={globalSearch}
onChange={(e) => setGlobalSearch(e.target.value)}
placeholder="Search agents by name, code..."
className="text-sm"
/>
<Button
icon="pi pi-search"
className="p-button-primary"
onClick={handleSearch}
size="small"
/>
</div>
</div>
{/* Agents List with VirtualScroller */}
{agentsData.length === 0 && !isPending ? (
<div className="flex justify-center items-center flex-1">
<div className="max-w-xs">
<Lottie animationData={NoDataLottie} loop autoplay />
<p className="text-center text-sm text-gray-600 dark:text-gray-400 mt-2">
No agents assigned
</p>
</div>
</div>
) : (
// <div className="flex-1 overflow-hidden">
<div className="card flex justify-content-center">
<VirtualScroller
items={agentsData}
itemSize={80}
itemTemplate={agentItemTemplate}
// className="h-full"
// style={{ height: '100%' }}
className="border-1 surface-border border-round"
style={{ width: '200px', height: '200px' }}
/>
</div>
)}
{/* Loading Spinner */}
{isPending && (
<div className="flex justify-center items-center p-4 border-t border-gray-200 dark:border-gray-700">
<ProgressSpinner style={{ width: "25px", height: "25px" }} />
<span className="ml-2 text-sm">Loading agents...</span>
</div>
)}
{/* Load More Button */}
{hasNextPage && (
<div className="p-3 border-t border-gray-200 dark:border-gray-700">
<Button
label={isFetchingNextPage ? "Loading more agents..." : "Load More"}
className="w-full p-button-outlined p-button-sm"
icon={isFetchingNextPage ? "pi pi-spinner pi-spin" : "pi pi-chevron-down"}
onClick={() => fetchNextPage()}
disabled={isFetchingNextPage}
size="small"
/>
</div>
)}
{!hasNextPage && agentsData.length > 0 && (
<div className="p-3 border-t border-gray-200 dark:border-gray-700">
<Button
label="All agents loaded"
className="w-full p-button-secondary p-button-sm"
disabled
size="small"
/>
</div>
)}
</div>
)}
</div>
);
}
export default UserAgentsListing;
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the reported behavior in the UserAgentsListing component, focusing on the VirtualScroller container and its commented sizing classes and styles. Compare rendering with and without the card wrapper, and verify that the scroller remains visible and adopts the intended dimensions without relying on that wrapper.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, tailwindcss, typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100