Repeat Password Validation - admin-on-rest

I try to implement a page for create new users with admin-on-rest. I want to add two fields for Password and Repeat Password Can you guide me. I use <TextInput source="password" type="password" validate={ required }/> for Password field but what about Repeat Password?
How We can validate Repeat Password?
I havent any idea for how we can create this page.

Answer by this question validate confirmation password in redux form is works.
My example:
import React from 'react';
import { SimpleForm, TextInput, Create } from 'react-admin';
import { required, email } from 'react-admin';
const PasswordValidate = values => {
const errors = {};
if (!values.username) {
errors.username = 'Required';
}
if (!values.password) {
errors.password = 'Required';
}
if (!values.confirmPassword ) {
errors.confirmPassword = 'Required' ;
} else if (values.confirmPassword !== values.password) {
errors.confirmPassword = 'Password mismatched' ;
}
return errors;
};
export const UserCreate = (props) => (
<Create {...props}>
<SimpleForm validate={PasswordValidate}>
<TextInput source="email" type="email" validate={[required(), email()]} />
<TextInput source="username" />
<TextInput label="Password" source="password" validate={required()} />
<TextInput label="Repeat password" source="confirmPassword" type="password" validate={required()} />
</SimpleForm>
</Create>
);

Related

yup validation with dynamic data

I have a yup validation with API response requirement for a react hook form.
My form is like:
import React from "react";
import useForm from "react-hook-form";
import { schema } from "./schema";
import { useTestProps } from "./useTestProps";
function Sub({ title, showForm }) {
const { register, handleSubmit, errors } = useForm({
validationSchema: schema
});
const { data } = useTestProps();
const onSubmit = (data) => {
//submit form
};
// console.log(errors);
return (
<div>
<form onSubmit={handleSubmit(onSubmit)}>
<label>{title}</label>
<input type="text" name="iip" ref={register} />
<br />
{errors.iip && <p>{errors.iip.message}</p>}
<br />
<label>Email</label>
<input type="text" name="email" ref={register} />
<br />
{errors.email && <p>{errors.email.message}</p>}
<br />
<input type="submit" />
</form>
</div>
);
}
export default Sub;
Validation schema of the form is like this,
//schema.js
import * as yup from "yup";
export const schema = yup.object().shape({
iip: yup
.string()
.required()
.test("validate with testProps", "iip not found", (value) => {
// validate that value should be one of testProps
// if value is in data, return true, or return false
return true
}),
email: yup.string().email().required()
});
My requirement is to validate iip field with data returned from API call in useTestProps which is like this,
{
"data": ["test1", "test2", "test3"]
}
How can I access data in schema object test where I can compare user entered value with JSON response?

Unable to render redux form select input choices dynamically

I am trying to populate a select menu in redux forms dynamically.
I've been using the debugging tools in chrome and can see that the 'departments' variable sees the array list
({departments.map(department => <option key={department} value={department}>{department}</option>)}
but the final choice list isn't populating. I'm guessing it has something to do with the renderSelectField function, but I'm not sure what I am overlooking?
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
import { connect } from 'react-redux';
import isValidEmail from 'sane-email-validation';
class SimpleReduxForm extends Component {
constructor(props) {
super(props);
this.onSubmit = this.onSubmit.bind(this);
this.renderSelectField = this.renderSelectField.bind(this);
}
onSubmit = async (data) => {
try {
let response = await fetch('/api/getRecords', {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-type': 'application/json'
}
});
let responseJson = await response.json();
//display success message to user
alert('Form successfully submitted')
return responseJson;
//reset form
} catch (error) {
alert(error);
}
}
renderInputField(field) {
return (
<div className="form-group">
<label htmlFor={field.input.name}>{field.label}</label>
<div className="field">
<input placeholder={field.label} {...field.input} className="form-control" type={field.input.type} />
</div>
</div>
)
}
renderSelectField(field) {
return (
<div className="form-group">
<label htmlFor={field.input.name}>{field.label}</label>
<div className="field">
<select {...field.input}
className="form-control"
defaultselection={field.defaultSelection}
><option>{field.defaultselection}</option></select>
</div>
</div>
)
}
render() {
const { handleSubmit, pristine, reset, submitting, invalid } = this.props;
//Options for select - this should be an AJAX call to a table to get options list
const departments = ["Dept 1", "Dept 2", "Dept 3"]
return (
<form onSubmit={handleSubmit(this.onSubmit)}>
<Field
label="Username"
name="username"
component={this.renderInputField}
type="text"
/>
<Field
label="Email"
name="email"
component={this.renderInputField}
type="email"
/>
<Field
label="Age"
name="num_field"
component={this.renderInputField}
type="text"
/>
<Field
label="Department"
name="department"
defaultselection="Select..."
component={this.renderSelectField}>
{departments.map(department => <option key={department} value={department}>{department}</option>)}
</Field>
<div>
<button type="submit" className="btn btn-primary" disabled={pristine || submitting}>Submit</button>
<button type="button" className="btn btn-warning" disabled={pristine || submitting} onClick={reset}> Clear Values </button>
</div>
</form >
)
}
}
//Validate Errors Before Submission
const validate = (values) => {
//create errors object
const errors = {}
/*Example showing to check is a field contains data
* if no, submission == invalid*/
if (!values.username) {
errors.username = 'Required!'
}
/*check to see if email is provided and that submission is an actual email address*/
if (!values.email) {
errors.email = 'Required!'
} else if (!isValidEmail(values.email)) {
errors.email = 'Invalid Email!'
}
/* Example to show that the length of a field
* can be checked as part of validation */
if (values.num_field < 2) {
errors.num_field = "Must be at least 10 years old"
}
return errors
}
const mapStateToProps = state => ({
SimpleReduxForm: state.form.SimpleReduxForm
});
export default reduxForm({
validate,
form: 'SimpleReduxForm',
enableReinitialize: true,
keepDirtyOnReinitialize: true,
})(connect(mapStateToProps)(SimpleReduxForm));
I figured it out. Just in case anyone else runs into this issue. I needed to add {field.children} into the renderSelectField function. So the final function looks like:
renderSelectField(field) {
return (
<div className="form-group">
<label htmlFor={field.input.name}>{field.label}</label>
<select {...field.input}
className="form-control"
defaultselection={field.defaultSelection}
><option>{field.defaultselection}</option>{field.children}</select>
</div>
)
}

How to change value of input in Admin on Rest from another component in Create form?

I've reduced this to a very simple case for ease of discussion. I have a simple create form with 1 field and 1 button. I would like the button to set the value of the TextInput to "Hello" without submitting the form. How is this possible in admin on rest? eg:
export const TestCreate = (props) => (
<Create title={<TestTitle />} {...props}>
<SimpleForm>
<TextInput source="title" />
<TitleSetterButton />
</SimpleForm>
</Create>
);
Been struggling with this for a while - it should be simple so hopefully there's an easy answer.
I was able to setup a Sample form using their example application
// in src/posts.js
import React from 'react';
import { List, Edit, Create, Datagrid, ReferenceField, TextField, EditButton, DisabledInput, LongTextInput, ReferenceInput, required, SelectInput, SimpleForm, TextInput } from 'admin-on-rest';
import FlatButton from 'material-ui/FlatButton';
export const PostList = (props) => (
<List {...props}>
<Datagrid>
<TextField source="id" />
<ReferenceField label="User" source="userId" reference="users">
<TextField source="name" />
</ReferenceField>
<TextField source="title" />
<TextField source="body" />
<EditButton />
</Datagrid>
</List>
);
const PostTitle = ({ record }) => {
return <span>Post {record ? `"${record.title}"` : ''}</span>;
};
export class Testing extends React.Component {
render() {
return <input type="text" />
}
}
export class PostCreate extends React.Component {
componentDidMount() {
console.log(this)
}
constructor(props) {
super(props);
this.handleCustomClick = this.handleCustomClick.bind(this);
// this.fieldOptions = this.fieldOptions.bind(this);
}
handleCustomClick() {
this.fields.title.handleInputBlur("tarun lalwani");
this.fields.body.handleInputBlur("this is how you change it!");
}
render () {
let refOptions = {ref: (e) => {
if (e && e.constructor && e.props && e.props.name) {
this.fields = this.fields || {};
this.fields[e.props.name] = e;
}
}}
return (
<Edit title={<PostTitle />} {...this.props}>
<SimpleForm>
<DisabledInput source="id" />
<ReferenceInput label="User" source="userId" reference="users" validate={required}>
<SelectInput optionText="name" />
</ReferenceInput>
<TextInput source="title" options={refOptions}/>
<LongTextInput source="body" options={refOptions}/>
<FlatButton primary label="Set Value" onClick={this.handleCustomClick} />
</SimpleForm>
</Edit>
);
}
}
Before click of the button
After clicking Set Value
And then after clicking Save you can see the actual changed values get posted

How to solve this issue with redux form? It shows syntax error

We are going to use redux form for all our app's forms. The app may have 5 different forms for different purposes. The trouble with this first form is that it shows syntax error. But before implementing redux form it was worked with the same syntax. What is the problem with this code?
import React, {Component} from "react";
import {Text, Image, KeyboardAvoidingView, Platform,View} from "react-native";
import {
Content,
Form,
Item,
Input,
Icon,
Button,
ListItem,
Row,
Col,
Grid,
Toast,
Container,
Left,
Right,
Body
} from "native-base";
import styles from "../styles/formstyle";
import { Field, reduxForm } from "redux-form";
const required = value => (value ? undefined : "Required");
const maxLength = max => value => (value && value.length > max ? `Must be ${max} characters or less` : undefined);
const maxLength15 = maxLength(15);
const minLength = min => value => (value && value.length < min ? `Must be ${min} characters or more` : undefined);
const minLength8 = minLength(8);
const email = value =>
value && !/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value) ? "Invalid email address" : undefined;
const alphaNumeric = value => (value && /[^a-zA-Z0-9 ]/i.test(value) ? "Only alphanumeric characters" : undefined);
class SigninScreen extends Component {
static navigationOptions = {
gesturesEnabled: false,
};
renderInput({ input, label, type, meta: { touched, error, warning } }) {
return (
<Item style={styles.item}
error={error && touched}
>
<Icon
active
name="mail"
style={styles.icon}
/>
<Input
{...input.name="email"}
ref={c => (this.textInput = c)}
placeholder="Email"
placeholderTextColor="#a4916d"
style={styles.input}
/>
</Item>
<Item style={styles.item} error={error && touched}>
<Icon
active
name="lock"
style={styles.icon}
/>
<Input
{...input.name="password"}
ref={c => (this.textInput = c)}
secureTextEntry={true}
placeholder="Password"
placeholderTextColor="#a4916d"
style={styles.input}
/>
</Item>
);
}
login() {
if (this.props.valid) {
this.props.navigation.navigate("Drawer");
} else {
Toast.show({
text: "Enter Valid Username & password!",
duration: 2000,
position: "top",
textStyle: { textAlign: "center" },
});
}
}
render() {
return (
<Image style={background.img} source={require("../img/cover.jpg")}>
<Container style={styles.content}>
<Form>
<Field name="email"
validate={[email, required]} />
<Field
name="password"
component={this.renderInput}
validate={[alphaNumeric, minLength8, maxLength15, required]}
/>
</Form>
<ListItem
style={styles.list}
>
<Left>
<Button
primary
full
style={{width:"90%"}}
onPress={() => this.props.navigation.navigate("Signup")}
>
<Text style={{color: "#0dc49d"}}>fb</Text>
</Button>
</Left>
<Body/>
<Right>
<Button
danger
full
onPress={() =>
this.props.navigation.navigate("Forgetpass")}
>
<Text style={{color: "#0dc49d"}}>google</Text>
</Button>
</Right>
</ListItem>
<Button
full
style={{backgroundColor: "#0dc49d", width:"90%"}}
onPress={() => this.login()}
>
<Text style={{color:"#ffffff"}}>Sign In</Text>
</Button>
</Container>
</Image>
);
}
}
export default reduxForm({
form: 'test'
})(SigninScreen)
It says JSX elements must be wrapped an enclosing tag. Eslint shows the second component inside the renderinput. I am using it with native-base. What can cause this error? Also, can you check please if the communication within renderinput and fields component is right? I am not sure that after solving the syntax error this code will work :(
Thanks in advance!
renderInput method is returning two different items. You need to wrap them into a single wrapped component like the error is saying.
Example
renderInput({ input, label, type, meta: { touched, error, warning } }) {
return (
<View>
<Item style={styles.item} error={error && touched}>
<Icon active name="mail" style={styles.icon} />
<Input {...input.name="email"} ref={c => (this.textInput = c)} placeholder="Email" placeholderTextColor="#a4916d" style={styles.input} />
</Item>
<Item style={styles.item} error={error && touched}>
<Icon active name="lock" style={styles.icon} />
<Input {...input.name="password"} ref={c => (this.textInput = c)} secureTextEntry={true} placeholder="Password" placeholderTextColor="#a4916d" style={styles.input} />
</Item>
</View>
);
}

Force update of a ReferenceManyField from an custom action in admin-on-rest

I have the following Edit component:
const UserEdit = (props) => (
<Edit {...props}>
<TabbedForm>
<FormTab label="Main">
<TextInput source="var1" />
<TextInput source="var2" />
<TextInput source="var3" />
</FormTab>
<FormTab label="Images">
<ImageUploadComponant />
<ReferenceManyField label="Images" reference="images" target="user_id">
<Datagrid>
<ImageField source="url" />
<DeleteButton />
</Datagrid>
</ReferenceManyField>
</FormTab>
</TabbedForm>
</Edit>
);
The ImageUploadComponant is juste a componant that enable the user to upload a file, and it creates a new object on the API related to the ReferenceManyField :
class ImageUpload extends Component {
onDrop = async files => {
/* Uploading the file */
};
render() {
return (
/* A componant with an upload field */
);
}
}
ImageUpload.propTypes = {
push: PropTypes.func,
record: PropTypes.object,
showNotification: PropTypes.func,
};
export default connect(null, {
showNotification: showNotificationAction,
push: pushAction,
})(ImageUpload);
After the /* Uploading the file */ block, I would like to refresh the ReferenceManyField so the fresh uploaded image is shown.
I guess I have to put some kind of redux / sagas message, but I didn't manage to perform it. Any idea ?

Resources