Access the values of components in react-admin - reactjs

I want to access values of components. Because I'll use it to access to another data. For example;
<ArrayInput source='services'>
<SimpleFormIterator>
<ReferenceInput label="Service Type"
source="serviceType"
reference="servicetypes"
validate={required()}>
<SelectInput optionText={GAMMA_CONSTANTS.SOURCE_ID} />
</ReferenceInput>
{(this.state.serviceTypes && this.state.serviceTypes.length > 0) ?
this.state.serviceTypes.filter(serviceType => {
return serviceType.id === (**source="serviceType"**)
})[0]["datapointtype"].map((feature, index) => {
return <TextInput source={index} label="deneme" />
})
: null}
</SimpleFormIterator>
</ArrayInput>
I want to access it in the filter method. Is there a way to do that?

You can use something like this:
import { FormDataConsumer } from 'react-admin';
const PostEdit = (props) => (
<Edit {...props}>
<SimpleForm>
<BooleanInput source="hasEmail" />
<FormDataConsumer>
{({ formData, ...rest }) => formData.hasEmail &&
<TextInput source="email" {...rest} />
}
</FormDataConsumer>
</SimpleForm>
</Edit>
);
Reference: https://marmelab.com/react-admin/Inputs.html#hiding-inputs-based-on-other-inputs
You're not limited to hide/show things. In your case, you should be able to avoid using state and directly access formData.serviceTypes

Related

React Admin: How to run method before return <Edit> form view

Im making app in React-Admin Framework. Now I am creating the edit form:
<Resource name="order" edit={OrderEdit} />
And I want to decide whether to show Edit View based on a record.
E.g If record 'id' from data provider is equal to 5, display an alert and redirect to the main view '/orders':
const OrderEdit = (props) => {
const checkId = (id) => {
if(id==5){
alert('You cannot edit an order where ID Input is 5');
useRedirect('/orders');
}
}
//checkId(this.props.record.id); <=== HERE IS MY PROBLEM
/*
1. this.props.record.id = undefined;
2. props.record.id = undefined;
3. record.id = undefined;
*/
return (
<Edit {...props} >
<SimpleForm>
<TextInput
source="id"
label="ID Input"
/>
</SimpleForm>
</Edit>
);
};
export default OrderEdit;
But I don't know how to access record.id before return.
I know that I can do it with FunctionField:
<FunctionField
render={(record) =>{
if(record) checkId(record.id)
return null;
}}
label="test"
/>
But it doesn't look right.
You do not need this. since its a functional component where you pass props as an argument.
You could return null if record.id is not the correct, which is the same way as saying display nothing:
if (checkId(this.props.record.id)) return null
return (
<Edit {...props} >
<SimpleForm>
<TextInput
source="id"
label="ID Input"
/>
</SimpleForm>
</Edit>
);
Or more clean:
return checkId(this.props.record.id) ? null : (
<Edit {...props} >
<SimpleForm>
<TextInput
source="id"
label="ID Input"
/>
</SimpleForm>
</Edit>
);
I don't know if you can access the record in the Edit view component because it calls a getOne internally and forward the record to its child. So you can eventually wrap your form to access it like:
const WrapperForm = (props) => {
const {record} = props;
return (
<SimpleForm {...props}>
<TextInput source="id" label="ID Input"/>
</SimpleForm>
);
}

Conditionally render TextFields in react-admin [duplicate]

Some fields I want to only show if they have a value. I would expect to do this like so:
<Show {...props} >
<SimpleShowLayout>
{ props.record.id ? <TextField source="id" />: null }
</SimpleShowLayout>
</Show>
But that doesn't work. I can make it somewhat work by making each field a higher order component, but I wanted to do something cleaner. Here's the HOC method I have:
const exists = WrappedComponent => props => props.record[props.source] ?
<WrappedComponent {...props} />: null;
const ExistsTextField = exists(TextField);
// then in the component:
<Show {...props} >
<SimpleShowLayout>
<ExistsTextField source="id" />
</SimpleShowLayout>
</Show>
This correctly shows the value, but strips the label.
We need to update our documentation about this. In the mean time, you can find informations about how to achieve that in the upgrade guide: https://github.com/marmelab/react-admin/blob/master/UPGRADE.md#aor-dependent-input-was-removed
Here's an example:
import { ShowController, ShowView, SimpleShowLayout, TextField } from 'react-admin';
const UserShow = props => (
<ShowController {...props}>
{controllerProps =>
<ShowView {...props} {...controllerProps}>
<SimpleShowLayout>
<TextField source="username" />
{controllerProps.record && controllerProps.record.hasEmail &&
<TextField source="email" />
}
</SimpleShowLayout>
</ShowView>
}
</ShowController>
);
Maybe this way can be useful
import { FormDataConsumer } from 'react-admin'
<FormDataConsumer>
{
({ formData, ...rest}) => formData.id &&
<>
<ExistsTextField source="id" />
</>
}
</FormDataConsumer>

how to get data from form to redirect SimpleForm edit

I have a react component below. and I want to redirect with the dataset response from dataset_id. How to i get the data to put into the redirect field for simple form ?
export const qnaEdit = props => {
return (
<Edit {...props}>
<SimpleForm
redirect="data_sets">
<TextInput disabled source="id" />
<TextInput datasetid="dataset_id" />
<TextInput source="question" />
<TextInput multiline source="short_answer" />
{/* <RichTextField multiline source="url" /> */}
</SimpleForm>
</Edit>
);}
RedirectTo can be a function, not only string, so it should help.
if (typeof redirectTo === 'function') {
return redirectTo(basePath, id, data);
}
https://github.com/marmelab/react-admin/blob/master/packages/ra-core/src/util/resolveRedirectTo.ts
Documentation: https://marmelab.com/react-admin/CreateEdit.html#redirection-after-submission
You can also pass a custom route (e.g. “/home”) or a function as redirect prop value. For example, if you want to redirect to a page related to the current object:
// redirect to the related Author show page
const redirect = (basePath, id, data) => `/author/${data.author_id}/show`;
export const PostEdit = (props) => {
<Edit {...props}>
<SimpleForm redirect={redirect}>
...
</SimpleForm>
</Edit>
);
This affects both

How to hide other tag if i click a RadioButtonGroupInput tag in React?

I want to hide other tag when i click the RadioButton in React..
When RadioButtonGroupInput clicked, i want to hide ReferenceInput tag
If you know how.. please comment ..
const UserEdit = ({ classes, ...props }) => (
<Edit {...props}>
<SimpleForm>
<TextInput source="username" validate={required()}/>
<TextInput source="email" validate={[required(),email()]}/>
<TextInput source="phoneNumber" validate={[required(),minLength(10),number()]}/>
<RadioButtonGroupInput label="Type"
source="userType"
choices={types}
optionText="id"
validate={required()}
onChange={(event,id) => (id === "COMPANY") ? console.log(id) : console.log(event)}/>
<ReferenceInput label="Company" source="company.id" reference="companies">
<SelectInput optionText="name" />
</ReferenceInput>
</SimpleForm>
</Edit>
);
You can integrate the useState() hook to coordinate with RadioButtonGroupInput. It lets us define a checked value and a setChecked function used specifically to update checked.
When the onChange() event-listener is triggered, we will toggle the checked value. Then we used checked to conditional render ReferenceInput
import React, { useState } from "react
const UserEdit = ({ classes, ...props }) => (
//creates a state-value and a state-updater function. Set default as false.
const [ checked, setChecked ] = useState(false)
<Edit {...props}>
<SimpleForm>
<TextInput source="username" validate={required()}/>
<TextInput source="email" validate={[required(),email()]}/>
<TextInput source="phoneNumber" validate={[required(),minLength(10),number()]}/>
<RadioButtonGroupInput
label="Type"
source="userType"
choices={types}
optionText="id"
validate={required()}
onChange={() => setChecked(!checked)}/> //set to opposite of current-value
//if not checked, then we will display ReferenceInput, if checked, hide.
{ !checked && (
<ReferenceInput label="Company" source="company.id" reference="companies">
<SelectInput optionText="name" />
</ReferenceInput>
)}
</SimpleForm>
</Edit>
);
Finally, I did it. see the following sources.
const UserCreate = ({ classes, ...props }) => {
const types = [
{id:'INDIVIDUAL'},
{id:'COMPANY'}
];
const [checked,setChecked] = useState(true);
const onClickRadioBtn = (event,id) => {
(id === "COMPANY") ? setChecked(false) : setChecked(true)
}
return(
<Create {...props}>
<SimpleForm>
<TextInput source="username" validate={required()}/>
<TextInput source="password" validate={required()}/>
<TextInput source="email" validate={[required(),email()]}/>
<TextInput source="phoneNumber" validate={[required(),minLength(10),number()]}/>
<RadioButtonGroupInput label="Type"
source="userType"
choices={types}
optionText="id"
validate={required()}
onChange={onClickRadioBtn}/>
{ !checked && (
<ReferenceInput label="Company" source="company.id" reference="companies">
<SelectInput optionText="name" />
</ReferenceInput>
)}
</SimpleForm>
</Create>
);
};

undefined id at edit page in react admin

I'm using react admin for a project, I need to add descriptions to users: admins are allowed to add/edit to any user and only user themselves can edit their own description. I am able to show the edit button to the logged in user, but every time it hits the actual edit page, the user id becomes undefined and it routes me to a bad url error page. I'm new to react and react-admin so I don't really understand what's causing it become undefined.
Thanks in advance!
//in userList.js
export const UserList = ({ permissions, ...props }) => (
<List {...props} bulkActionButtons={false} sort={{ field: 'display_name', order: 'ASC'}} >
<Datagrid>
<TextField source="display_name" label="User Name" />
<RoleField source="role" label="User Role" />
<TextField source="description" label="Description"/>
<BooleanField source="active" />
<FormDataConsumer>
{({ formData }) => (formData.id === JSON.parse(user_info).id) &&
<EditButton/>
}
</FormDataConsumer>
{permissions === "administrator" &&<EditButton />}
</Datagrid>
</List>
);
//in useredit.js
export const UserEdit = ({permissions, ...props}) => (
<Edit {...props}>
<SimpleForm toolbar={<SaveOnlyToolbar />}>
<DisabledInput source="display_name" />
<DisabledInput source="distinguished_names" />
<TextInput resource="description" label="Description"/>
<FormDataConsumer>
{({ formData }) => formData.is_only_admin ?
<React.Fragment>
<DisabledInput source="role" />
<DisabledInput source="active" />
</React.Fragment>
:
<React.Fragment>
<SelectInput source="role" label="Role" choices={RoleChoices}/>
<BooleanInput source="active" />
</React.Fragment>
}
</FormDataConsumer>
</SimpleForm>
</Edit>
);
//in app.js
const content = () => {
return (
<Admin
authProvider={authProvider}
dataProvider={dataProvider}
customRoutes={[
<Route exact path="/help" component={Help}/>,
<Route exact path="/" component={Dashboard}/>]}
loginPage={false}
>
{role => [
(role === 'administrator' || role === 'read_only' || role === 'user') ? <Resource name='user' list={UserList} icon={PeopleIcon} edit={role === 'administrator' || role === 'user' ? UserEdit : null}/> : null,
]}
</Admin>
);
}
return <>{content()}</>;
};
export default App;
The <FormDataConsumer>component works only inside forms: <SimpleForm>, <TabbedForm> and others. In the <List>component will not work.

Resources