How to combine create and edit page in react-admin - react-admin

I am new for the react and react-admin, but I am now using it in our project, everything is good, but there is one thing I don't know how to make it. in our application. the create and edit page almost same, the only difference is some fields are disabled in edit view, so I want to combine create and edit, is there any document about it. I searched it but it seems not an easy way to do it, it's appreciated if can get some sample code. thank you !!!
Hi #Mads, thank you for your answer, I update the question here. what I mean is last time, i also create a separate form like what you did and I insert the component directly as below (e.g. <Form/>). it will get an error: the invalid value for prop ‘save’ on tag
I am just curious what's the difference with this way ({form('edit')})
<Edit {...props} undoable={false} style={{width: '100%'}}> <Form/> </Edit>

You can do something like this:
const form = type => (
<SimpleForm>
<TextInput source="name"/>
{type === 'create' ? <TextInput source="created_at"/> : ''}
</SimpleForm>
);
export const EditView = ({classes, ...props}) => {
return (
<Edit {...props} undoable={false} style={{width: '100%'}}>
{form('edit')}
</Edit>
);
};
export const CreateView = ({classes, ...props}) => {
return (
<Edit {...props} undoable={false} style={{width: '100%'}}>
{form('create')}
</Edit>
);
};

I had a similar struggle and this is what I ended up doing:
// This is the reusable form component
const CategoryForm = (props) => (
<SimpleForm {...props}>
<TextInput source="name" label="Nome" />
{props.type === "edit" && <p>This element only shows in edit mode</p>}
</SimpleForm>
);
// Edit View Component
export const CategoryEdit = (props) => (
<Edit {...props}>
{/* Reusable form component with type prop set to 'edit' */}
<CategoryForm type="edit" />
</Edit>
);
// Create View Component
export const CategoryCreate = (props) => (
<Create {...props}>
{/* Reusable form component with type prop set to 'create' */}
<CategoryForm type="create" />
</Create>
);

Related

Passing state via route.params with React Navigation returning undefined

I'm attempting to pass a 'passcode' state as params in my React Native app.
I'm doing this by passing params into a 'navigation.navigate' call.
However, every time I navigate to the next screen, it's returning 'undefined' for 'route.params'.
For reference, here is my component I'm passing data FROM:
const SignUpPasscodeScreen = ({ navigation }) => {
const [passcode, setPasscode] = useState(0)
return (
<View>
<View style={styles.mainView}>
<SubLogo />
<Heading title="Set passcode" />
<SubHeading content="You'll need this anytime you need to access your account." />
<Input inputText={ text => setPasscode(text) } inputValue={passcode} />
</View>
<View style={styles.subView}>
<CtaButton text="Continue" onPressFunction={ () => navigation.navigate({ routeName: 'SignUpLegalName', params: { passcode } } ) } />
</View>
</View>
)
}
And here's the component I'm passing data to, and where the error occurs upon navigation:
const SignUpLegalName = ({ route, navigation }) => {
const { passcode } = route.params
return (
<View>
<View style={styles.mainView}>
<SubLogo />
<Heading title="Tell us your name" />
<SubHeading content="This needs to be the same as what's on your passport, or any other form of recognised ID." />
<Input />
<Input />
</View>
<View style={styles.subView}>
<CtaButton text="Continue" onPressFunction={ () => navigation.navigate('SignUpLink')} />
</View>
</View>
)
}
I've tried two forms of passing the props through:
Passing it in as a second argument
Passing it in as a 'params' object as shown above
Both should work according to the documentation - link here
For reference, this is my route structure:
const switchNavigator = createSwitchNavigator({
loginFlow: createStackNavigator({
SignUpPasscode: SignUpPasscodeScreen,
SignUpLegalName: SignUpLegalName,
})
});
The above structure doesn't say to me that it's a nested structure which therefore requires any additional work to pass it through...
Can someone help? It'd be appreciated as it's giving me a headache!
Have a try with below code in the button press event:
<CtaButton
text="Continue"
onPressFunction={() => navigation.navigate('SignUpLegalName',{ passcode })}
/>

Display Field in Edit Form

Currently, if I try to place a Field into an Edit form, the field doesn't display at all. There is no errors in the console or the terminal about why it wont.
Example:
<Edit undoable={false} {...props}>
<SimpleForm>
<FormRow>
<TextField source="id"/>
<TextField source="name"/>
</FormRow>
</SimpleForm>
</Edit>
will not display either of these on the page load, it will simply be blank.
Is there any way to use fields in the Edit form?
You need to pass in the record prop (and basePath if its a reference).
The Edit component does not get the record prop so create a form component and it will get passed the record as a prop
eg.
const ProjectEdit: FC<EditComponentProps> = props => {
const classes = useStyles();
return (
<RA.Edit {...props} title={<ProjectTitle />}>
<RA.SimpleForm>
<ProjectForm />
</RA.SimpleForm>
</RA.Edit>
);
};
export const ProjectForm = (props: any) => {
return (
<Box flex={1} mr={{ md: 0, lg: '1em' }}>
<RA.TextInput source="name" fullWidth={true} />
<Typography variant="h6" gutterBottom>
Tasks
</Typography>
<RA.TextField
source="name"
fullWidth={true}
record={props.record}
/>
<RA.ReferenceManyField
label="Tasks"
reference="Task"
target="projectId"
fullWidth={true}
record={props.record}
basePath="/Task"
>
<RA.SingleFieldList fullWidth={true}>
<RA.ChipField source="name" fullWidth={true} />
</RA.SingleFieldList>
</RA.ReferenceManyField>
</Box>
);
};

useState getting confused when using multiple components

The action taken to update the state in a functional component is incorrectly updating the state of the final component loaded.
I have simplified what I'm doing to very simple code. I'm wondering if I'm missing something in why this does not work
This is parent component that loops to create subcomponents.
{scoreDays.length >0 ? scoreDays.map((el,idx) =>(
<ScoringDay key={idx} date ={el.day} score={el.score}
channels={el.channels} />
)) : null}
This is the ScoringDay component. I'm simply using a button press to update the text in state and have it displayed.
const ScoringDay = props => {
[expanded, setExpanded] = useState(false);
[test, setTest] = useState('starting text');
return(
<View>
<Text>
{test}
</Text>
<Text onPress={() =>setTest('Clicked here')}>Update value</Text>
</View>
)
In my example, 3 "ScoringDay" components are shown on the screen. However, no matter which text "Update value" I click, it always updates the text on the last component.
Why isn't the action being applied to the correct component?? I am using an index on the key...but not sure what else needs to be changed here?
Run the status change from parent to child.
[testtext, setTestText] = useState('starting text');
...
{scoreDays.length >0 ? scoreDays.map((el,idx) =>(
<ScoringDay key={idx} date ={el.day} score={el.score}
channels={el.channels} testtext={testtext} setTestText={setTestText} />
)) : null}
Used
const ScoringDay = props => {
[expanded, setExpanded] = useState(false);
const { testtext, setTestText} = props
return(
<View>
<Text>
{testtext}
</Text>
<Text onPress={() =>setTestText('Clicked here')}>Update value</Text>
</View>
)

React Native, Passing Navigation to Stateless Flatlist component

Currently I have:
return(
<View style={{flex: 1, paddingTop:20}}>
<FlatList
data={this.state.dataSource}
renderItem={(data) => <EventCard eventinfo = {data.item} navigation=
{this.props.navigation}/>}
keyExtractor={(item) => item.eventname}
/>
and
const EventCard = ({eventinfo, navigation}) => {
return (
<TouchableOpacity style={{backgroundColor: 'transparent'}} onPress= {()
=> navigation.navigate('CurrRes')}>
I dont understand why Navigation cant be evaluated in my Eventcard, and navigation doesnt work. Any help would be appreciated.
(yes withnavigation is imported in the first file and the project runs but crashes when one of the flatlist items is pressed)
The error i get is
undefined is not an object (evaluating 'navigation.navigate')
Here is an example I found to explain it better.
You need to access props differently than just a normal function with deconstruction.
const Child = (props) => {
return (
<div style={{backgroundColor: props.eyeColor}} />
)
}
https://medium.com/#PhilipAndrews/react-how-to-access-props-in-a-functional-component-6bd4200b9e0b
Nevermind, I had to export the actual list with navigation so each of its nested stateless components could navigate. Sorry!

React-native Input HOC for redux-form loses focus after type a symbol

I'm trying to use redux-form, but, as I read, I need HOC for Input field to replace onTextChange to onChange. I have:
import React from 'react';
import {Input} from 'native-base';
export default function InputField(props) {
const { input, ...inputProps } = props;
return (
<Input
{...inputProps}
onChangeText={input.onChange}
onBlur={input.onBlur}
onFocus={input.onFocus}
value={input.value}
/>
);
};
and use it in my form:
<Item style={{marginTop: 10, width: "100%"}}>
<Field name="login" component={(props) => {
return (
<InputField {...props} keyboardType="email-address" placeholder='E-mail' />
)
}}/>
</Item>
But every time I type key, the field loses focus. Some "experts" recommend use focus() function. But what if I edit text in the middle of it?
Any solutions? Or maybe native-base have compatible textfield component?
It is strange, but it works ))
function InputFieldEmail(props) {
return <InputField {...props} keyboardType="email-address" placeholder='E-mail' />;
}
and use it instead arrow functions
<Field name="login" component={InputFieldEmail}/>
I think it's strange )
You must provide the InputField component as a prop so that its value is constant or put it outside the Item component, when it is inside another, every time the state of the upper level is updated, the lower level is forced to return. to start.
If your Input is inside an Item you are probably using a FlatList and your goal is to put it in the header.
You can try something like this:
<View style={{marginTop: 10, width: "100%"}}>
<Field name="login" component={(props) => {
return (
<InputField {...props} keyboardType="email-address" placeholder='E-mail' />
)
}}/>
</View>
<FlatList
ListHeaderComponent={() => {
<Item>
</Item>
}}
/>
Remember to put the styles that were in Item in View.