Tech TutorBangla Web Documentation
Portfolio
HomeHTMLCSSTailwind CSSJavaScriptTypeScriptReactNext.jsNode.jsExpressSocket.IOExpoWordPressPostgreSQLPrismaPostgresNestJSMongoDBDockerTanStackTanStack TableRTK QueryGitGitHub
  • TanStack Table Documentation12টি অধ্যায়
প্রযুক্তি নির্বাচন
HomeHTMLCSSTailwind CSSJavaScriptTypeScriptReactNext.jsNode.jsExpressSocket.IOExpoWordPressPostgreSQLPrismaPostgresNestJSMongoDBDockerTanStackTanStack TableRTK QueryGitGitHub
  • Introduction
  • Installation & Setup
  • Core Concepts
  • Column Definitions
  • Row Models
  • Sorting
  • Filtering
  • Pagination
  • Row Selection
  • Column Management
  • Server-side Mode
  • Advanced Features
  1. Docs
  2. TanStack Table
  3. Row Selection — row বাছাই
TanStack TableIntermediate

Row Selection — row বাছাই

rowSelection state, checkbox কলাম, indeterminate select-all, নির্বাচিত row পড়া, bulk action, server-side select — বাংলায়।

37টি অংশবাংলা ভাষায়

টেবিলে সবচেয়ে ব্যবহৃত ইন্টারঅ্যাকশন — একাধিক row বেছে নিয়ে একসাথে কিছু করা: মুছে ফেলা, এক্সপোর্ট, বাল্ক স্টক আপডেট।

state — অবজেক্ট, অ্যারে নয়

// rowSelection state এর আকার
type RowSelectionState = Record<string, boolean>;

// {
//   "p-01": true,
//   "p-04": true,
//   "p-09": true,
// }
//
// ⚠️ key হলো row.id — তাই getRowId না দিলে index ("0", "1") হয়ে যায়

key হলো row.id — এটাই সবচেয়ে জরুরি কথা। getRowId: (row) => row.id না দিলে id হয় index, আর index filter/sort বদলালে বদলে যায়। তখন selection ভেঙে যায় — ভুল row বেছে নেওয়া হয়।

সেটআপ

const [rowSelection, setRowSelection] = useState<RowSelectionState>({});

const table = useReactTable({
  data,
  columns,
  getCoreRowModel: getCoreRowModel(),
  getFilteredRowModel: getFilteredRowModel(),
  getSortedRowModel: getSortedRowModel(),
  getPaginationRowModel: getPaginationRowModel(),

  enableRowSelection: true,   // default true, বন্ধ করতে চাইলে false
  state: { rowSelection },
  onRowSelectionChange: setRowSelection,

  getRowId: (row) => row.id,   // ← এটা না দিলে selection ভাঙবে
});

এখানে চারটি row model দিয়েছি কারণ select-all checkbox বলতে চায় "এই পেজের সব" নাকি "সব filter করা row"। Model না থাকলে পার্শ্বপ্রতিক্রিয়াগুলো ভুল হয়।

Checkbox কলাম

import { Checkbox } from "@/components/ui/checkbox";
import type { ColumnDef } from "@tanstack/react-table";

export const selectColumn: ColumnDef<Product> = {
  id: "select",
  header: ({ table }) => {
    const allSelected = table.getIsAllPageRowsSelected();
    const someSelected = table.getIsSomePageRowsSelected();

    return (
      <Checkbox
        aria-label="সব row নির্বাচন"
        checked={allSelected ? true : someSelected ? "indeterminate" : false}
        onCheckedChange={(checked) =>
          table.toggleAllPageRowsSelected(checked === true)
        }
      />
    );
  },
  cell: ({ row }) => (
    <Checkbox
      aria-label={`${row.original.name} নির্বাচন`}
      checked={row.getIsSelected()}
      onCheckedChange={(checked) => row.toggleSelected(checked === true)}
    />
  ),

  // এই কলামটা সাজানো/লুকানো হবে না
  enableSorting: false,
  enableHiding: false,
}

checked-এ তিনটা অবস্থা দেওয়া যায়: true, false, আর "indeterminate" — অর্থাৎ "কিছু বেছে নেওয়া হয়েছে কিন্তু সব নয়"। shadcn-এর Checkbox এটা সামলায়।

const columns: ColumnDef<Product>[] = [
  selectColumn,               // ← সবসময় প্রথমে
  { accessorKey: "name", header: "পণ্যের নাম" },
  // … বাকি কলাম
];

তিন ধরনের select-all

এটা সবচেয়ে বেশি ভুল হওয়া জায়গা। "সব" বলতে কী বোঝায় — পেজের সব, নাকি পুরো filter করা ডেটার সব?

methodকী করেকখন
getIsAllPageRowsSelected()বর্তমান পেজের সব বেছে আছে কিনাসাধারণ সবচেয়ে বেশি ব্যবহৃত
getIsSomePageRowsSelected()পেজের কিছু বেছে আছেindeterminate দেখাতে
getIsAllRowsSelected()সব row বেছে আছে (সব পেজ মিলিয়ে)"সব ফলাফল বেছে নিন" লিংক দেখাতে
header: ({ table }) => {
  const all = table.getIsAllPageRowsSelected();
  const some = table.getIsSomePageRowsSelected();

  return (
    <div className="flex items-center gap-2">
      <Checkbox
        checked={all ? true : some ? "indeterminate" : false}
        onCheckedChange={(v) =>
          table.toggleAllPageRowsSelected(v === true)
        }
      />

      {/* সব পেজ ধরে বেছে নিতে চাইলে লিংক */}
      {some && !all && table.getFilteredRowModel().rows.length > table.getRowModel().rows.length && (
        <Button
          variant="link"
          size="sm"
          className="h-auto p-0 text-xs"
          onClick={() => table.toggleAllRowsSelected(true)}
        >
          সব {table.getFilteredRowModel().rows.length}টি বেছে নিন
        </Button>
      )}
    </div>
  );
}}
Gmail-এর ধাঁচ

Gmail/Mail-এও ঠিক এভাবেই হয়: পেজের সব বেছে নিলে checkbox tick হয়, কিন্তু অন্য পেজে কিছু বাকি থাকলে একটা ছোট লিংক দেখায় — "সব ১২৮৪টি বেছে নিন"। ছোট ডেটায় এটা ব্যবহার না করলেও চলে, কিন্তু user কী বেছে নিচ্ছেন তা পরিষ্কার থাকে।

নির্বাচিত row পড়া

// রেন্ডার করা (যেমন selection-এর উপর ভিত্তি করে style)
row.getIsSelected()          // boolean
row.getToggleSelectedHandler()

// পুরো টেবিল থেকে
const selectedRows = table.getSelectedRowModel().rows;  // Row<Product>[]
const selectedIds = table.getSelectedRowModel().flatRows.map(
  (row) => row.id,
);

// state সরাসরি পড়া
Object.keys(table.getState().rowSelection);  // ⚠️ false ও থাকতে পারে

// ✅ নির্ভরযোগ্য উপায়
const ids = table
  .getSelectedRowModel()
  .rows.map((row) => row.original.id);

Object.keys(state.rowSelection) ব্যবহার করবেন না — TanStack খালি করার সময় { "p-01": false } রেখে দিতে পারে, ফলে অচেনা id চলে যায়। getSelectedRowModel() সবসময় পরিষ্কার ফলাফল দেয়।

Row selection-এর উপর effect

useEffect(() => {
  const ids = table.getSelectedRowModel().rows.map((r) => r.original.id);
  setSelectedCount(ids.length);
}, [table.getState().rowSelection]);

effect-এর ভেতরে getSelectedRowModel() না পড়ে state থেকে হিসাব করাই নিরাপদ — প্রতিটি render-এ নতুন array তৈরি হওয়ায় effect বারবার চলতে।

Bulk action বার

const selectedRows = table.getSelectedRowModel().rows;
const count = selectedRows.length;

{count > 0 && (
  <div className="flex items-center gap-3 border-b bg-muted/40 px-4 py-2">
    <span className="text-sm font-medium">
      {count}টি নির্বাচিত
    </span>

    <div className="ml-auto flex gap-2">
      <Button
        variant="outline"
        size="sm"
        onClick={async () => {
          const ids = selectedRows.map((r) => r.original.id);
          await deleteProducts(ids);
          table.resetRowSelection();
        }}
      >
        মুছে ফেলুন
      </Button>

      <Button
        variant="ghost"
        size="sm"
        onClick={() => table.resetRowSelection()}
      >
        বাতিল
      </Button>
    </div>
  </div>
)}
// নির্বাচিত সব বাদ দিতে চাইলে
row.toggleSelected(false);

// ঐ পেজের সব বাদ
table.toggleAllPageRowsSelected(false);

// পুরো ফলাফল বাদ
table.resetRowSelection();

শুধু কিছু কলামে select করা যায়

{
  accessorKey: "name",
  cell: ({ row }) => (
    <Checkbox
      checked={row.getIsSelected()}
      disabled={!row.getCanSelect()}
      onCheckedChange={(v) => row.toggleSelected(v === true)}
    />
  ),
}

// কোনো শর্তে select বন্ধ
const table = useReactTable({
  // …
  enableRowSelection: (row) => row.original.isActive, // inactive select করা যাবে না
});

Server-side selection

অনেক অ্যাপে একটি পেজের বেছে নেওয়া কাজ নেই — মোট নির্বাচিতের সংখ্যা দেখাতে হয়, আর সব পরিবর্তন API-তে যায়।

// নির্বাচিত id গুলো URL-এ
useEffect(() => {
  const ids = table.getSelectedRowModel().rows.map((r) => r.original.id);
  const params = new URLSearchParams();
  if (ids.length) params.set("ids", ids.join(","));
  router.replace(`?${params.toString()}`, { scroll: false });
}, [table.getState().rowSelection]);
সব পেজ বেছে নিলে কী হয়

getIsAllRowsSelected() + toggleAllRowsSelected(true) ব্যবহার করলে selection state-এ প্রতিটি row-এর id চলে আসে — ১০,০০০ row হলে ১০,০০০ key। খুব বড় ডেটায় বদলে একটা পতাকা ("all matching: true) রাখুন, আর mutation-এ সেটা ব্যবহার করে queryKey-এর সাথে মিলিয়ে server-এ বুঝিয়ে দিন।

সাধারণ বাগ

ঘটনাকারণসমাধান
সাজালে selection চলে যায়getRowId নেইgetRowId: (row) => row.id
পেজ বদলালে selection থেকে যায়এটাই আসলে চাওয়াgetRowModel().rows দিয়ে render
checkbox-এ indeterminate দেখায় নাchecked তিন অবস্থায় দেননি"indeterminate" pass করুন
filter করলে selection চলে যায়expected behaviourtable.resetRowSelection()
মুছে ফেলার পরে বাকি row-ও হারায়অপ্রয়োজনীয় re-rendergetRowId ঠিক আছে কিনা দেখুন
selected count ভুলObject.keys(state)getSelectedRowModel() ব্যবহার করুন
header checkbox কাজ করে নাonCheckedChange এ checked সরাসরি দিয়েছেনchecked === true করে toggle* কল

সারসংক্ষেপ

  • rowSelection হলো Record<rowId, boolean> — তাই getRowId জরুরি
  • header checkbox-এ তিনটা অবস্থা: true / "indeterminate" / false
  • "সব" মানে পেজের সব, নাকি পুরো ফলাফলের সব — স্পষ্ট করে নিন
  • নির্বাচিত row পড়তে getSelectedRowModel(), Object.keys নয়

পরবর্তী

এতক্ষণ কলামগুলো সবসময় দেখা যাচ্ছিল। পরের অধ্যায়ে column management — visibility, order, pinning (sticky কলাম) আর width resize।

শেষ প্যারায় নিজে practice করুন — কোড কপি করে নিজের এডিটরে চালিয়ে দেখুন।
আগেরPagination — পেজ ভাগপরেরColumn Management — visibility, order, pinning ও sizing
এই পেজে
Tech Tutor

বাংলায় ওয়েব ডেভেলপমেন্ট ডকুমেন্টেশন শিখুন — ধাপে ধাপে।

Homeসব ডকুমেন্টেশনQuick Startআমার নোটস

© 2026 Tech Tutor. বাংলায় শিখুন, বাংলায় গড়ুন।

mdanamolhasan1998@gmail.com