How to exclude fields from SimpleForm - admin-on-rest

I know <SimpleForm> is using redux-form.
I want to exclude specific fields from being sent when I submit the form.
When I edit my entity "User" the RestClient send a GET_ONE request and my API response this:
{
name: "Lior",
age: "100",
type: "Manager",
}
The <SimpleForm> is like this:
<SimpleForm>
<TextInput source="name"/>
<TextInput source="age"/>
</SimpleForm>
When I send the form, the fields I see in the request are: name, age and type even when there is no "input" or "field" for type.
How can I avoid from "type" to be sent?
The API has to return it, I need it for <Show> and more..
I don't to hard coded my RestClient just to remove the "type" because it is
not happening just in "User" model but in many other models.
I don't want to "usset" it on the API controller side.
Thanks!

There's no react-admin way to doing this. I think a restClient middleware is the way to go, but you don't want that. What you can do is to create a HOC using mapProps of recompose and wrap SimpleForm with it. Something like (untested code):
const withLimitedProps = properties => mapProps(({save,...props}) => ({...props,save: (record,redirect) => save(properties.reduce((acc,property)=>{
acc[property]=record[property]
},{})});
const UserEditForm = withLimitedProps(['name','age'])(SimpleForm)
The save prop is proxied, and the record that's submitted is reduced. You can always add more functionality, like selecting the current fields from the redux-form state and reducing on them only. This would give the behaviour that you want.

You can customize your restClient to only send a subset of fields when calling UPDATE:
case UPDATE:
url = `${apiUrl}/${resource}/${params.id}`;
options.method = 'PUT';
const { name, age } = params.data; // type is ignored
options.body = JSON.stringify({ name, age });

Related

Best practice for adding 'dynamic' fields in GraphQL?

I have a GraphQL API that provides information about YouTube videos. One of the fields I set up is the YouTube video ID (e.g. dQw4w9WgXcQ), and from that, you can deduce the video URL (https://www.youtube.com/watch?v=dQw4w9WgXcQ) and thumbnail e.g.
If I didn't want to store the URL as its own field and still wanted to have a field called 'videoUrl' that constructs the URL on the fly as part of the response, do I just splice that in at the resolver level after the database query, or is there a better way?
So the resolver could look something like this:
recentVideos: async (_parent, _args, ctx) => {
const videos = await ctx.prisma.video.findMany({
orderBy: {
publishedAt: 'desc',
},
take: 24 });
return videos.map(video => { videoUrl: `https://youtube.com/watch?v=${video.youtubeId}`, ...video });
}
As long as I set up videoUrl as a String in the type definition too, is this a solid practice? In this scenario, it would always do the work of populating the videoUrl field, regardless of whether it's part of the result fields or not.
PS: The sample youtube video I'm using here is Never Gonna Give You Up, don't say you haven't been warned!

In GraphQL, can you change the structure of the output in an alias?

Let's say I've got a GraphQL query that looks like this:
query {
Todo {
label
is_completed
id
}
}
But the client that consumes the data from this query needs a data structure that's a bit different- e.g. a TypeScript interface like:
interface Todo {
title: string // "title" is just a different name for "label"
data: {
is_completed: boolean
id: number
}
}
It's easy enough to just use an alias to return label as title. But is there any way to make it return both is_completed and id under an alias called data?
There is no way to do that. Either change the schema to reflect the client's needs or transform the response after it is fetched on the client side.

redux-form initialize FieldArray

I'm trying to create a redux form which integrates many aspects of redux-form.
To give a better introduction to the project I would like to share the main goals with you.
At the moment i've a dynamic form which can be extended with participants. Each participant has a superior. On user input (Async.Creatable React select) I request (call to API) all users based on the text. To sum up, an Autosuggestion. When receiving the users I make a second call to get the corresponding superior. Afterwards I would like to autofill the fields for the participant as well as for the superior.
Everything works quite well for the first participant + superior. Unlike the first participant the second superior is not getting autofilled.
Is it required to call the initialize action (redux-form) manual, when mutating the initalValues Property?
The function getFormData access the current state. These state is as expected and contains the following data.
These state is created with the LOAD action of redux-form
initial
:
attendees
:
Array(2) <-- Autofilled fields [{name: FirstTest, firstName: FirstTest}, {name: SecondTest, firstName: SecondTest}]
const mapStateToProps = (state) => {
const attendeesFromFormData = getFormData(state, REGISTRATION_FORM, [{}]).attendees
const attendees = attendeesFromFormData ? attendeesFromFormData : [{}]
return {
initialValues: {
attendees: attendees
}
}
}
export default connect(mapStateToProps, {searchADUser, autoFillAttendee, getADUser})(reduxForm({
form: REGISTRATION_FORM,
enableReinitialize: true
})(RegistrationForm))
Okay after a bit research and testing I find a simple solution for my problem.
Each time you add a participant you have to initialize manually the redux-form.

Admin-on-rest: Filter based on different data

I have a REST endpoint to get a set of 'groups', where each group consists of a name and an id. I have successfully implemented that as a resource in admin-on-rest.
Now I have another REST endpoint for getting users, but I can only get users for a specific group, not all users in general. The REST endpoint requires me to provide the group id as part of the url. There is no groupId in a user object though, because there reference is the other way around, group -> users.
What I want is to display the 'name' of a group in the filter dropdown of the users list view and then to use the 'id' of a group to pass to the rest client in order to load the respective users.
I have already implemented the call in my restclient as follows:
case 'users': {
switch(type) {
case 'GET_LIST': {
return getUsers(token, params.filter.id)
.then(response => ({ data: response.data, total: response.data.length }));
}
}
break;
}
And in the list view of my users resource component, I have implemented a filter like this:
const UsersFilter = ({ ...props }) => (
<Filter {...props}>
<ReferenceInput source="id" reference="groups">
<SelectInput optionText="name" />
</ReferenceInput>
</Filter>
);
Now, this doesn't work. In the filter I just one entry called 'Id', and there is an error message saying something like "cannot find targetusergroup with id==undefined".
What can I do?
Sorry,
it actually did work, but I was too stupid to use the User Interface. I didn't know, that I have to first select a filter, before I can use it. And I also forgot to give my group filter a label, that's why it only said 'id' in the filter menu.
Now it works.

ASP.NET Web API: convert Object Literal to CLR class

My Web API controller needs to take in a property bag, i.e. a list of key-value pairs, which it will use to insert or update records of indeterminate type. My ideal code would look something like this. This example would be to insert a new record.
Route:
/api/data/{EntityName}
Data from client, passed in using jQuery.ajax() (or similar) with POST:
URI:
http://mysite/api/data/employee
Post data:
"values":
{"FirstName":"Jim",
"LasName":"Nobody",
"StartDate": new Date(),
"Salary": 100000 }
Web API Controller function:
public HttpResponseMessage PutRecord(string entity, ??? values)
{
// confirm valid entity, look up metadata.
// Take values from "values" and feed them into my framework to insert a new employee.
}
What is the ideal configuration to accomplish this? What would be the type for "values" in the controller method - possibly a Dictionary< string,object>?
Thanks very much for your help.
If you create a model that has all of the properties, the model binder will map your post data directly to the model.
So your post would look more like this:
$.post(url, {FirstName:'Jim', LasName: 'NoBody',StartDate: someDate, Salary: 10000},
function(data){
// do something with callback
});
And your action would look like:
public HttpResponseMessage PutRecord(string entity, employeeModel model)
{
// confirm valid entity, look up metadata.
// Take values from "values" and feed them into my framework to insert a new employee.
}
This is a tad more type safe than the property bag approach, and save you a lot of casting and typing issues.

Resources