I have a react-admin app. Here I have an <Edit>-component:
export const UserEdit = (props) => {
const value = useContext(AppContext);
return (
<div className="container-lg px-0 pb-1">
<Edit queryOptions={{ meta: { customerId: value.selectedCustomer.id } }} mutationOptions={{ meta: { customerId: value.selectedCustomer.id } }}>
<SimpleForm /*toolbar={<EditToolbar />}*/>
<Stack direction="row" spacing={2}>
<Stack direction="column">
<TextInput source="id" required disabled />
<TextInput source="first_name" required />
<TextInput source="last_name" required />
<TextInput source="email" type="email" required disabled />
<PreferredLanguageField {...props} />
</Stack>
<Stack direction="column">
<FormDataConsumer>
{({ formData, ...rest }) => (
<>
<BooleanInput source="active_customer_membership.user_access_manager" label="Can manage users" disabled={value.user.id == formData.id} />
<UserRoleInput {...props} disabled={value.user.id == formData.id} />
<UserAccessInput {...props} formData={formData} disabled={value.user.id == formData.id} />
</>
)}
</FormDataConsumer>
</Stack>
</Stack>
</SimpleForm>
</Edit>
</div>
);
};
In Main I have a dataProvider:
const baseDataProvider = restProvider('../../api/user_access_management/v01', fetchUtils.fetchJson);
export const dataProvider = withLifecycleCallbacks(baseDataProvider, [
{
resource: 'users',
beforeGetList: async (params, dataProvider) => {
params.filter.customer_id = params.meta.customerId;
return params
},
afterGetList: async (result, dataProvider) => {
// Format the retrieved data to the correct format for react-admin.
return {
data: result.data.users,
total: result.total
};
},
beforeGetOne: async (params, dataProvider) => {
return params
},
afterGetOne: async (result, dataProvider) => {
return {
data: result.data.user
};
},
beforeUpdate: async (params, dataProvider) => {
params.data = {
user: DataHelper.formUser(params.data, params.meta.customerId)
};
return params;
},
afterUpdate: async (result, dataProvider) => {
return {
data: result.data.user
};
},
beforeCreate: async (params, dataProvider) => {
params.data = {
user: DataHelper.formUser(params.data, params.meta.customerId),
};
return params;
},
afterCreate: async (result, dataProvider) => {
return {
data: result.data.user
};
},
},
]);
And how the App is initialized:
const Main = (props) => {
const [customer, setCustomer] = useState(props.props.customer);
useEffect(() => {
setCustomer(props.props.customer);
}, [props.props.customer]);
const [customers, setCustomers] = useState(props.props.customers);
useEffect(() => {
setCustomers(props.props.customers);
}, [props.props.customers]);
const [user, setUser] = useState(props.props.user);
useEffect(() => {
setUser(props.props.user);
}, [props.props.user]);
const [selectedCustomer, setSelectedCustomer] = useState(props.props.customers[0]);
useEffect(() => {
setSelectedCustomer(props.props.customers[0]);
}, [props.props.selectedCustomer]);
return (
<AppContext.Provider value={{ customer: customer, customers: customers, user: user, selectedCustomer: selectedCustomer, setSelectedCustomer: setSelectedCustomer }}>
<Admin dataProvider={dataProvider} layout={CustomLayout}>
<Resource name="users"
list={<UserList />}
edit={<UserEdit />}
create={<UserCreate />}
/>
</Admin>
</AppContext.Provider>
);
}
export default Main;
My problem now is that for the Create / Update, I can add customer_id as a field to send to the backend (they're POST / PUT requests). Same for GetList, here I can add customer_id as filter: params.filter.customer_id = params.meta.customerId;
However, I also need the customer_id in the backend for the GetOne-request. The <Edit> component has queryOptions={{ meta: { customerId: value.selectedCustomer.id } }}, and I see that in the beforeGetOne -callback. However, adding it to filters (like I do for GetList) doesn't seem to work.
How would I add query-parameters to the URL for the GetOne-request?
restProvider, which I assume you get fromra-data-simple-rest, doesn't support passing filters togetOne, as it is non-standard (in most implementations, theidis all you need to get a single record).You will probably need to build the HTTP request manually (using
fetch).Alternatively, you can pass the
customerIdas a custom HTTP Header but then your API needs to know how to use it.Lastly, you can also choose to override the
getOneimplementation of your dataProvider, to have it callgetListinstead, with the filter, and return only the first result.Regarding the call to
delete, you need to pass a customtoolbarto your<SimpleForm>, and in it include a custom<DeleteButton>on which you can passmutationOptions.PS: in case you are using the
customerIdas a way to build a multi-tenant app, be sure to read Multi-Tenant Single-Page Apps: Dos and Don'ts to avoid the most common mistakes.