DeleteButton

DeleteButton

The <DeleteButton> component displays a button that deletes the current record after user confirmation. It must be used inside a RecordContext.

Usage

Use it in a DataTable or Show page:

import { DataTable, EditButton, DeleteButton } from '@/components/admin';

const PostList = () => (
  <DataTable>
    <DataTable.Col source="title" />
    <DataTable.Col source="status" />
    <DataTable.Col label="Actions">
      <div className="flex gap-2">
        <EditButton />
        <DeleteButton />
      </div>
    </DataTable.Col>
  </DataTable>
);

Installation

Terminal
npx better-admin add delete-button

Props

PropRequiredTypeDefaultDescription
labelOptionalstring"Delete"Button label text
recordOptionalobjectFrom contextRecord to delete
resourceOptionalstringFrom contextResource name
confirmTitleOptionalstring"Delete?"Confirmation dialog title
confirmContentOptionalstring"Are you sure?"Confirmation message
mutationOptionsOptionalobject-React Query mutation options
redirectOptionalstring | false"list"Where to redirect after delete

With Confirmation

By default, DeleteButton shows a confirmation dialog:

<DeleteButton
  confirmTitle="Delete Post?"
  confirmContent="This action cannot be undone."
/>

Custom Labels

<DeleteButton label="Remove" />
<DeleteButton label="Delete Forever" />

With better-query

DeleteButton integrates with better-query for deletion:

import { DeleteButton } from '@/components/admin';
import { useQuery } from 'better-admin';

export function UserDeleteButton({ userId }: { userId: string }) {
  const { remove } = useQuery("user", query);

  return (
    <DeleteButton
      record={{ id: userId }}
      mutationOptions={{
        onSuccess: () => {
          console.log('User deleted');
        },
      }}
    />
  );
}

With Permissions

Control visibility based on user permissions:

import { DeleteButton } from '@/components/admin';
import { useBetterAuth } from 'better-admin';
import { useRecordContext } from '@/lib/hooks';

export function ProtectedDeleteButton() {
  const { user } = useBetterAuth();
  const record = useRecordContext();
  
  const canDelete = user?.role === 'admin' || user?.id === record?.author_id;

  if (!canDelete) return null;
  
  return <DeleteButton />;
}

Redirect After Delete

Control where to redirect after deletion:

<DeleteButton redirect="list" /> {/* Go to list page */}
<DeleteButton redirect={false} /> {/* Stay on same page */}
<DeleteButton redirect="/custom-page" /> {/* Custom redirect */}

Custom Confirmation

Customize the confirmation dialog:

<DeleteButton
  confirmTitle="Permanently Delete?"
  confirmContent={
    <div>
      <p>This will permanently delete the record.</p>
      <p className="text-destructive font-semibold mt-2">
        This action cannot be undone!
      </p>
    </div>
  }
/>

Bulk Delete

For deleting multiple records, use BulkDeleteButton:

import { BulkDeleteButton } from '@/components/admin';

<DataTable>
  <DataTable.Col source="id" />
  <DataTable.Col source="name" />
  <DataTable.BulkActions>
    <BulkDeleteButton />
  </DataTable.BulkActions>
</DataTable>

Complete Example

import {
  Show,
  SimpleShowLayout,
  TextField,
  DateField,
  EditButton,
  DeleteButton,
} from '@/components/admin';
import { useQuery } from 'better-admin';
import { query } from '@/lib/query';
import { useBetterAuth } from 'better-admin';

export function PostShow({ id }: { id: string }) {
  const { data } = useQuery("post", query);
  const { user } = useBetterAuth();
  
  const canDelete = user?.role === 'admin';

  return (
    <Show
      resource="post"
      id={id}
      actions={
        <>
          <EditButton />
          {canDelete && (
            <DeleteButton
              confirmTitle="Delete Post?"
              confirmContent="This post will be permanently deleted."
              redirect="list"
            />
          )}
        </>
      }
    >
      <SimpleShowLayout>
        <TextField source="title" />
        <TextField source="content" />
        <DateField source="published_at" />
      </SimpleShowLayout>
    </Show>
  );
}

Error Handling

Handle deletion errors:

<DeleteButton
  mutationOptions={{
    onError: (error) => {
      console.error('Failed to delete:', error);
      // Show notification
    },
    onSuccess: () => {
      // Show success notification
    },
  }}
/>

Optimistic Update

Use optimistic updates for better UX:

import { useQueryClient } from '@tanstack/react-query';
import { DeleteButton } from '@/components/admin';

export function OptimisticDeleteButton() {
  const queryClient = useQueryClient();

  return (
    <DeleteButton
      mutationOptions={{
        onMutate: async (deletedId) => {
          // Cancel outgoing queries
          await queryClient.cancelQueries(['posts']);
          
          // Snapshot previous value
          const previousPosts = queryClient.getQueryData(['posts']);
          
          // Optimistically remove from cache
          queryClient.setQueryData(['posts'], (old: any) =>
            old?.filter((post: any) => post.id !== deletedId)
          );
          
          return { previousPosts };
        },
        onError: (err, deletedId, context: any) => {
          // Rollback on error
          queryClient.setQueryData(['posts'], context.previousPosts);
        },
      }}
    />
  );
}

Next Steps

On this page