documentation/versioned_docs/version-3.xx.xx/api-reference/chakra-ui/components/buttons/save.md
const { default: routerProvider } = RefineReactRouterV6;
const { default: simpleRest } = RefineSimpleRest;
setRefineProps({
routerProvider,
dataProvider: simpleRest("https://api.fake-rest.refine.dev"),
Layout: RefineChakra.Layout,
Sider: () => null,
catchAll: <RefineChakra.ErrorComponent />,
});
const Wrapper = ({ children }) => {
return (
<RefineChakra.ChakraProvider theme={RefineChakra.refineTheme}>
{children}
</RefineChakra.ChakraProvider>
);
};
<SaveButton> uses Chakra UI's <Button> component. It uses it for presantation purposes only. Some of the hooks that refine has adds features to this button.
:::info-tip Swizzle You can swizzle this component to customize it with the refine CLI :::
For example, let's add logic to the <SaveButton> component with the saveButtonProps returned by the useForm hook.
setInitialRoutes(["/posts/edit/123"]);
import { Refine } from "@pankod/refine-core";
import { EditButton } from "@pankod/refine-chakra-ui";
// visible-block-start
import {
Edit,
FormControl,
FormErrorMessage,
FormLabel,
Input,
Select,
} from "@pankod/refine-chakra-ui";
import { useSelect } from "@pankod/refine-core";
import { useForm } from "@pankod/refine-react-hook-form";
const PostEdit: React.FC = () => {
const {
refineCore: { formLoading, queryResult },
// highlight-next-line
saveButtonProps,
register,
formState: { errors },
resetField,
} = useForm<IPost>();
const { options } = useSelect({
resource: "categories",
defaultValue: queryResult?.data?.data.category.id,
queryOptions: { enabled: !!queryResult?.data?.data.category.id },
});
useEffect(() => {
resetField("category.id");
}, [options]);
return (
// highlight-next-line
<Edit isLoading={formLoading} saveButtonProps={saveButtonProps}>
<FormControl mb="3" isInvalid={!!errors?.title}>
<FormLabel>Title</FormLabel>
<Input
id="title"
type="text"
{...register("title", { required: "Title is required" })}
/>
<FormErrorMessage>{`${errors.title?.message}`}</FormErrorMessage>
</FormControl>
<FormControl mb="3" isInvalid={!!errors?.status}>
<FormLabel>Status</FormLabel>
<Select
id="content"
placeholder="Select Post Status"
{...register("status", {
required: "Status is required",
})}
>
<option>published</option>
<option>draft</option>
<option>rejected</option>
</Select>
<FormErrorMessage>{`${errors.status?.message}`}</FormErrorMessage>
</FormControl>
<FormControl mb="3" isInvalid={!!errors?.categoryId}>
<FormLabel>Category</FormLabel>
<Select
id="ca"
placeholder="Select Category"
{...register("category.id", {
required: true,
})}
>
{options?.map((option) => (
<option value={option.value} key={option.value}>
{option.label}
</option>
))}
</Select>
<FormErrorMessage>{`${errors.categoryId?.message}`}</FormErrorMessage>
</FormControl>
</Edit>
);
};
// visible-block-end
const App = () => {
return (
<Refine
notificationProvider={RefineChakra.notificationProvider()}
resources={[
{
name: "posts",
edit: PostEdit,
list: () => (
<RefineChakra.VStack alignItems="flex-start">
<RefineChakra.Text>This page is empty.</RefineChakra.Text>
<EditButton colorScheme="black" recordItemId="123">
Edit Item 123
</EditButton>
</RefineChakra.VStack>
),
},
]}
/>
);
};
render(
<Wrapper>
<App />
</Wrapper>,
);
interface ICategory {
id: number;
title: string;
}
interface IPost {
id: number;
title: string;
status: "published" | "draft" | "rejected";
category: { id: number };
}
hideTextIt is used to show and not show the text of the button. When true, only the button icon is visible.
setInitialRoutes(["/"]);
import { Refine } from "@pankod/refine-core";
// visible-block-start
import { SaveButton } from "@pankod/refine-chakra-ui";
const MySaveComponent = () => {
return <SaveButton hideText />;
};
// visible-block-end
const App = () => {
return (
<Refine
resources={[
{
name: "posts",
list: MySaveComponent,
},
]}
/>
);
};
render(
<Wrapper>
<App />
</Wrapper>,
);