How to make react-admin resource route default to show instead of edit? - react-admin

The react-admin docs explain the default routing for resources as:
/posts/:id maps to PostEdit
/posts/:id/show maps to PostShow
I'd like my app to default to viewing, and only allow editing if the user clicks the edit icon. However the default for all the reference links is to point to /resource/:id.
Is there a way to swap the routing such that /resource/:id maps to Show and /resource/:id/edit is used for Edit? Or maybe change the reference links to /resource/:id/show?

This may not be exactly the thing you are looking for, but default actions can be switched, so click on item can lead to show instead of edit:
https://marmelab.com/react-admin/List.html#the-datagrid-component
export const PostList = (props) => (
<List {...props}>
<Datagrid rowClick="show">
...
</Datagrid>
</List>
);

Reference links can be set to reference "show" by add link="show" to the ReferenceField.
See https://github.com/marmelab/react-admin/issues/247#issuecomment-287819508

You might want to create some custom routes matching your needs redirecting to custom Create/Show components like
const customRoutes = [
<Route key="editPost" exact path="/posts/:id" component={PostEdit} />,
<Route key="showPost" exact path="/posts/:id/show" component={PostShow} />,
];
function App() {
return (
<Admin
...
customRoutes={customRoutes}
>
...
</Admin>
)
}
Source: https://marmelab.com/react-admin/Admin.html#customroutes

Related

Edit field name is different from source field name

I'm working with a form and I need to submit a field that's called "Lang-en" however the field name in the get request is called "Lang".
Now I need to show the value of the field in the submit form using the "Lang" source however when I submit it, I want it to be submitted as "Lang-en".
Anyway to achieve this?
I realize It's not the best api but that's what I'm working with unfortunately.
Use the transform prop:
export const UserCreate = (props) => {
const transform = data => ({
...data,
fullName: `${data.firstName} ${data.lastName}`
});
return (
<Create {...props} transform={transform}>
...
</Create>
);
}
use URIEncode before transfer。。。

React-Admin: How to make <Filter> mandatory with "alwaysOn" using "list"

I couldn't find a way to ONLY FETCH or LIST resources, when a user fills in the <SelectInput> (as rendered by <ReferenceInput>).
Due to a domain restriction,I need to ask the user to choose some Customer in order to query the Orders.
Is that possible? How can I pull it off?
To be clear, in their Demo project, the "Orders" can be listed using "Customer" as a <Filter>. (see image below)
A workaround could be also valid. Thanks.
Ok, this is an interesting scenario.
Let's closely look at the resource, and how it routes to various components.In this case, our interest is within the <list> and what exactly it renders:
// Set up the filter
const CustomerFilter = (props) => (
<Filter {...props}>
// setup your `ReferenceInput` and `SelectInput`
</Filter>
);
// Within your rendered component (OrderList)
<List {...props} filters={<CustomerFilter />}>
<Datagrid>
{console.log(props)} // Look out for the `match.params` prop
// ...
// Check for "customer_name" param within your props (verbose)
{match.params.customer &&
<TextField label="Customer" source="customer_name" />
}
</Datagrid>
</List>
Please note: don't just copy/paste this code. It's a verbose version.
The implication is that you can render customer name (or whatever) within your list depending on a passed parameter.

choosing scene based on prop

We're using mobx along with react-native-router-flux. I want to load a different route based on a value from a mobx store. I'm trying to understand how to do this. So I have this from my store
const { authenticated, profile: { role } } = stores.authStore;
I pass the role as a prop to <PrivateRouter role={role} />. I want to select a <Scene> based on the value of role. All of this takes place in the App.js file. Any ideas on how I would do this? I'm new to both mobx and RNRF, so I'm not clear on how to accomplish this. Am I thinking correctly about this use case?
I finally got it resolved. So here's the solution in case someone encounters the same issue.
The problem was that profile is not exposed until the user is authenticated. So the app couldn't find it. The solution is as follows:
const render =
authenticated === undefined ? (
<LoadingScreen />
) : authenticated === true ? (
stores.authStore.profile.role === 'USER' ? (
<home />
) : (
<TrainerHome />
)
) : (
<PublicRouter />
);
return (
<Root>
<Provider {...stores}>{render}</Provider>
</Root>
);
Hope this provides help for future issues.

ArrayInput with SimpleFormIterator and conditional inputs

Let's say I have the following array in my create form
const CreateDefaults = {Inputs: [{id: "ID1", param: "a"},{id: "ID2", param: "b"}]};
and then I want to show extra TextInput only when id==="ID2"
export const MyCreate = withStyles(myStyles)(({ classes, ...props }) => (
<Create {...props}>
<SimpleForm defaultValue={CreateDefaults}>
<ArrayInput source="Inputs" {...props}>
<SimpleFormIterator {...props}>
<DisabledInput source="id" />
{/*this does not work*/}
{this.id === "ID2" ? (<TextInput source="ParamValue"/>) :null}
</SimpleFormIterator>
</ArrayInput>
</SimpleForm>
</Create>
));
How can I do something like that? I know that for the whole form, one can use FormDataConsumer. However, what can one do inside ArrayInput/SimpleFormIterator for each iteration?
How to access current object in iteration? I tried something like the answer given to the 'Custom Input do not receive record when inside ArrayInput' issue in the react-admin github page, but it still does not receive the record in custom input.
From the latest documentation here, you can see that if you use FormDataConsumer that is within an ArrayInput, you have a parameter called scopedFormData that you can use to get the current record and dereference that to get whatever fields you need. It usually also goes hand in hand with the getSource function you can use when setting the source within your FormDataConsumer.

How to populate a FlatList's header with data from the network?

I have a FlatList that displays a user's comments and I want to also populate the header with the user's profile (which is a different network call from the one fetching the comments).
Here's how render() looks like:
render() {
return (
<FlatList
data = {this.state.comments}
renderItem = {this.renderComment}
ListHeaderComponent={this.renderHeader}
keyExtractor={(comment, index) => comment.id}
/>
)
}
and then renderHeader looks like:
renderHeader() {
return (
<ProfileView user={this.state.profile} />
)
}
I use fetch in componentWillMount and then setState in order to get the data (this part works fine).
Now the error I get on the simulator is
undefined is not an object (evaluating 'this.state.profile')
but when I remove the renderHeader method, comments are fetched properly.
Since I'm very new to RN, can you help me understand what is wrong and how to fix it?
This looks like simply an issue with accessing context. When you run the renderHeader method called by the FlatList it doesn't know what this relates to.
So, you can simply set this.renderHeader = this.renderHeader.bind(this) in your constructor() method.
Alternatively, you should also be able to use an arrow function to call it, as this automatically refers to the correct this context.
ListHeaderComponent={() => this.renderHeader()}