Validate source parameter with typescript in react-admin - react-admin

I was wondering if it was possible (at the moment) to validate what is transmitted in the source property of inputs/fields.
I generate types (typescript) from my graphql introspection schema and I use it when I retrieve the controller so it would be awesome if typescript could validate that the source really exists in my record.
Example :
type Organisation {
id: number;
name: string;
}
const OrganisationShow = (props: ShowProps) => {
const { record, ...controllerProps } = useShowController<Organisation>(props);
return (
<ShowView
record={record}
{...controllerProps}
>
<TextField source="id" />
<TextField source="name" />
<TextField source="foo" /> // Typescript should deny it
</ShowView>
)
}
Is this something possible or an idea ?
Thanks for your help !

No, this is not possible for now. You would have to pass the type to all fields (<TextField<Organization> source="id" />, so I don't think it's very developer-friendly. And for nested source (e.g. author.name), I don't think it's feasible.

Related

Validating a SimpleForm field within React-Admin

I'm using an old version (2.9) of the React-Admin framework and having trouble validating a SimpleForm field.
I realize upgrading to a newer version is the way to go, but that will be a while.
I'm validating a field in a SimpleForm.
My validatefunction (below) returns an integer, 0 or above.
I want the validation to pass when that value is 0, but fail when the value is > 0. Currently, the form vails validation in all cases. Instead, I want it only fail when the return value is > 0.
Is there some way to specify that using some kind of expression on the validate line in the SimpleForm below?
const MyComponent = ({ dispatch, dataProvider, ...props }) => {
return (
<React.Fragment>
<SimpleForm>
...
<ReferenceInput
source="somefield"
validate={[ required(), validatefunction ]}
>
<SelectInput optionText="name" />
</ReferenceInput>
...
</SimpleForm>
</React.Fragment>
)
}
A better approach might be for my validatefunction to return undefined when the validation passes. But for reasons outside the scope here I haven't yet gotten that working.
Your validateFunction should return a string if there is an error.
const validatefunction = (value) => {
const validatorValue = oldValidateFunction(value);
if (validatorValue > 0) {
return 'error this does not validate';
}
}
See https://marmelab.com/react-admin/doc/2.9/CreateEdit.html#per-input-validation-custom-function-validator for the documentation of input validators.

In react-native-google-places-autocomplete , there is a method to set the inputs initial value, but it doesn't trigger the search query

I am trying to pass a saved search term string to prefill into google places autocomplete's input field. The setAddressText method they offer successfully prefills the input, but it does not trigger the search, so no dropdown options open. Only once you type something does the query run, so its obviously listening for an onChangeText event before it runs the query. I therefore don't see the point in the setAddressText method, if you then have to type again anyway. Surely there must be a way to trigger the search, without having to add / takeaway characters manually with the keyboard from the existing search term.
const { googleApiKey } = config
const ref = useRef()
useEffect(() => {
ref.current?.setAddressText(initialValue)
}, [])
return (
<View sx={{ flex: 1 }}>
<GooglePlacesAutocomplete
ref={ref}
placeholder={placeholder}
listViewDisplayed="true"
fetchDetails={true}
textInputProps={{
autoFocus: true,
...sx
}}
onPress={(data, details = null) => {
console.log("data", data, "details", details)
}}
query={{
key: googleApiKey,
language: "en",
components: "country:gb",
types: types ? types : null
}}
/>
</View>
)
}
Any wisdom on this would be greatly appreciated!
Full Disclosure: I maintain this library.
This is not currently supported by the library.
There is a feature request open here.

Unable to get renderStepIndicator working on react-native-step-indicator

I think I am not understanding the documentation correctly.
The documentation says: that is takes a Function that return a position: Number, or a stepStatus: which takes a String to render custom content inside step
My goal is to render a check mark instead of a number as it is by default.
I tried to return a string of 'test' and it does not work.
<StepIndicator
customStyles={customStyles}
currentPosition={this.state.currentPosition}
stepCount={this.state.stepCount}
renderStepIndicator={() => {
this.renderStepIndicator();
}}
labels={labels}
/>
and this is the function that return a string
renderStepIndicator() {
return 'test';
}
I am not sure what I am missing here. also I want to return an icon of checkmark. I have seen people doin git but I am not sure how if this only takes a string or an integer.
Here this function returns two parameters step position and step status. You can use this function like this,
<StepIndicator
customStyles={customStyles}
currentPosition={this.state.currentPosition}
stepCount={this.state.stepCount}
renderStepIndicator={(stepPosition,stepStatus) => {
this.renderStepIndicator(stepPosition,stepStatus);
}}
labels={labels}
/>
And the render function is like,
renderStepIndicator(stepPosition, stepStatus) {
return <Icon name={"check"} size={20} color={stepStatus === 'finished' ? "green" : "gray"} /> ;
}
This function render check icon. If you step was complete it show green check otherwise gray check.
For more details you can check this example,
https://github.com/24ark/react-native-step-indicator/blob/master/example/src/HorizontalStepIndicator.tsx
The above solution does not work for me so tried some changes and after some time I got this working solution if some are still facing this issue try using this code.
1. Put this code in your StepIndicator props
renderStepIndicator={({ position, stepStatus }) =>
renderStepIndicatorRender(position, stepStatus)
}
2. Create a function to render the icon
const renderStepIndicatorRender = (stepPosition, stepStatus) => {
return stepStatus === "finished" ? (
<Icon name="check" size={12} color="#fff" />
) : (
<Text>{stepPosition}</Text>
);

React-admin : Multiple image upload to s3 at once

I am trying to make a one-form creation page for an entity with an embedded array of other entities (which has another layer of depth). All of the entities and embedded entities are allowed (but not required) to have an image attached. The image input uses a custom api-platform endpoint to upload the image to AWS s3 and then returns a generated URL, which is being copied to according to text field. It works just the way I want when I am creating an entity with a single image field.
My Image Uploader:
(Feel free to criticize me about the way I check if the image has changed - I am happy to learn)
const ImageUploader = () => (
<>
<ImageInput source="imageUpload" label="image">
<ImageField source="imageUpload" title="title"/>
</ImageInput>
<ImageInput source="imageChecker" label="" options={{hidden: true}}>
</ImageInput>
<TextInput source="image" label="Image path"/>
<FormDataConsumer>
{
({formData}) => {
if (typeof formData === 'undefined' || typeof formData.imageUpload === 'undefined') {
return;
}
if (formData.imageChecker === null || formData.imageUpload !== formData.imageChecker) {
formData.imageChecker = formData.imageUpload;
formData.image = getImagePath(formData.imageUpload);
}
}
}
</FormDataConsumer>
</>
);
What is the problem:
The problem is whenever I have multiple ImageUploader fields in a Create field, uploading an image to one of the uploaders copies the effect for all the other uploaders and text inputs. The image itself is also uploaded to all of the image uploaders.
Example of my form with multiple image uploaders:
const FooBarCreate = props => (
<CreateGuesser {...props}>
...
<ImageUploader/>
<ArrayInput fullWidth={true} source="Foo">
<SimpleFormIterator>
...
<ImageUploader/>
<ArrayInput fullWidth={true} label="Bar" source="Bar">
<SimpleFormIterator>
...
<FormDataConsumer>
{
some logic unrelated to images
}
</FormDataConsumer>
</SimpleFormIterator>
</ArrayInput>
</SimpleFormIterator>
</ArrayInput>
</CreateGuesser>
);
My guess is that the program can't recognize which field I am trying to assign the value to, since their source names are all image and I have no idea how to solve this.
What I have tried:
surrounding the ImageUploader with a <SimpleForm> tag instead of empty tag with no luck, only generating save buttons all over the place.
The reason is that your multiple ImageInput share the same source "imageUpload". React-admin relies on source to read and modify form data. So when one ImageInput changes, the others all change along with it.
You gonna need to define different source for inside . The easiest way is to pass a source prefix property from outside.
like this:
<ImageUploader source="image1" />
const ImageUploader = ({source, ...props}) => (
<>
<ImageInput source=`${source}imageUpload` label="image">
<ImageField source="imageUpload" title="title"/>
</ImageInput>
<ImageInput source=`${source}imageChecker` label="" options={{hidden: true}}/>
<TextInput source=`${source}image` label="Image path"/>
<>
)

React-admin: getting error with nested item

When I create an Input like:
The rendering is ok, but when submiting I get the error:
index.js:1446 Warning: Missing translation for key: "Cannot read property 'name' of null"
export const PatientCreate = props => (
<Create {...props}>
<SimpleForm>
<NumberInput source="bsn" />
<TextInput source="patientname.firstname" />
<BooleanInput source="active" />
</SimpleForm>
</Create>
);
When I remove the nested item patientname.firstname, everythings works correctlty..Anyone idea ?
Using Prisma server data, but the error is in Create, before a put is happening, so I think I has something to do with react-admin..
Model is (Prisma MongoDB):
type Patient {
id: ID! #id
bsn: Int #unique
active: Boolean! #default(value: true)
patientname: Patientname
deceased: DateTime
}
type Patientname #embedded {
firstname: String
}
In React-admin documentaion:
https://marmelab.com/admin-on-rest/Inputs.html#textinput
<TextInput source="author.firstName" />
Tnx I anyone can help me ...
Paul
In your i18n translation files need to respect the nested reference.
React admin tries to translate using property `resources.[resourcename].fields.[fieldname] (see docs) if none is present it uses the string on source prop. If you have nested resources and no translation file with nested reference that error will be presented because can't find nested source.
If you create a translation file like this:
const language = {
resources: {
patient: {
patientname: {
firstname: "firstname"
}
}
}
};
Your problem is fixed. Take note that you need to add this translation resource to react-admin, more information can be found here.