I'm learning react admin and I have a simple page w/some filters like so:
import * as React from "react";
import { List, TextField, Datagrid, TextInput } from 'react-admin';
import { PostPaginationm } from "./MyPagination";
const postFilters = [
<TextInput label='Field' source="_Field-Name_matches" alwayson alwaysOn />,
<TextInput label='Index' source="_Index-Name" alwaysOn />,
<TextInput label='File' source="_File-Name" alwaysOn />,
<TextInput label='Db' source="_db-name" alwaysOn />,
];
export const IndexFieldSchemaList = () => (
<List filters={postFilters} pagination={<PostPaginationm/>}>
<Datagrid>
<TextField source="id" label="Id"/>
<TextField source="_db-name" label="Db"/>
<TextField source="_File-Name" label="File"/>
<TextField source="_Index-Seq" label="Seq"/>
<TextField source="_Index-Name" label="Index"/>
<TextField source="_Field-Name" label="Field"/>
<TextField source="_Ascending" label="Asc"/>
<TextField source="_Abbreviate" label="Abbr"/>
</Datagrid>
</List>
);
When I fill in one of the filters I get the following GET action:
GET http://localhost:12537/React/web/table/indexfieldschema?filter={"_File-Name":"extent"}&range=[0,49]&sort=["id","ASC"]
Previously I'd get something like this where the "q" field was added to the filter:
GET http://localhost:12537/React/web/table/indexfieldschema?filter={"q": "e", "_File-Name":"extent"}&range=[0,49]&sort=["id","ASC"]
I've coded the API to work with the "q" specification - w/out that it does a straight equality match which doesn't filter records the way I want.
How do I get the "q" field added to the filter the way I need? I'd note that when I originally coded this it added the "q" field so I'm not sure what changed to stop that behavior.
As it turns out the 'q' spec didn't work the way I thought it did and didn't give me the functionality I was after so the answer is how I got what I wanted.
You have to name your input "q":
const postFilters = [
<TextInput label="Search" source="q" alwaysOn />
];
What I ended up doing is taking advantage of the ability to add a "matches" query condition to a field which my backend'll use to do the search I want for each field.
const postFilters = [
<TextInput label='Field' source="_Field-Name_matches" alwayson alwaysOn />,
<TextInput label='Index' source="_Index-Name_matches" alwayson alwaysOn />,
<TextInput label='File' source="_File-Name" alwayson alwaysOn/>,
<TextInput label='Db' source="_db-name" alwayson alwaysOn/>
];
Related
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>
);
};
I'd like to know what are the data I'm working with, when using react-admin. (see them in the console to help debug)
For instance, when I'm working with a List:
import React from 'react';
import { Datagrid, List, TextField } from 'react-admin';
import { ListProps } from '../../types/admin/ListProps';
const ProductList = (props: ListProps): JSX.Element => {
console.log('ProductList.props', props);
return (
<List
{...props}
sort={{
field: 'titleEN',
order: 'DESC',
}}
>
<Datagrid rowClick="edit">
<TextField source="title" />
<TextField source="titleEN" label={'Title (EN)'} />
<TextField source="titleFR" label={'Title (FR)'} />
{/*<ArrayField source="images"><SingleFieldList><ChipField source="id" /></SingleFieldList></ArrayField>*/}
{/*<ReferenceArrayField source="imagesIds" reference="images"><TextField source="id" /></ReferenceArrayField>*/}
<TextField source="customer.label" label={'Customer'} />
<TextField source="price" />
</Datagrid>
</List>
);
};
export default ProductList;
How can I do that? I haven't found anything in the official doc https://marmelab.com/react-admin/List.html
This kind of logging can be displayed through the Data Provider. See https://marmelab.com/react-admin/DataProviders.html
For instance, with https://github.com/marcantoine/ra-data-graphql-prisma data provider, one such implementation could be https://github.com/UnlyEd/ra-data-graphql-prisma/commit/4031c5c3f2e97c479a9714df56da06653a908444
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>
);
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.
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>