below is my attempt to add a timestamp to when user submits form.
renderTimeStamp = ({ input, label }) => {
return (
{label}
<input {Date.now()} />
);
};
<Field
name="timestamp"
component={this.renderTimeStamp}
placeholder={moment().format()}
label="Time Stamp"
/>
Related
I managed to configure everything as expected with Formik, and the AJAX requests seems fine (it shows me the success message if I enable it), but the Netlify form section is still empty (even if the form is listed and acknowledged by Netlify).
This is my contact component:
(I think the problem is on my ajax code under the onSubmit function)
import React from 'react'
import { Formik, Form, Field, ErrorMessage } from 'formik'
import Layout from "../components/layout"
import SEO from "../components/seo"
const ContactForm = () => (
<Layout>
<SEO title="Form with Formik" />
<main class="page-contact-form">
<h1>Do your booking</h1>
<Formik
initialValues={{ email: '', name: '', start: '', end: '', message: '' }}
validate={values => {
let errors = {};
if (!values.email) {
errors.email = 'Required';
} else if (
!/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)
) {
errors.email = 'Invalid email address';
}
return errors;
}}
onSubmit={(values) => {
fetch("/", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: ({
"form-name": "contact",
...values
})
}).then(() => alert("Thank you!"))
}}
>
{({ isSubmitting }) => (
<Form name="contact" data-netlify="true" action="/grazie">
<input type="hidden" name="form-name" value="contact" />
<label>Name and Surname: <br />
<Field type="text" name="name" placeholder="Nome Cognome" />
<ErrorMessage name="name" component="div" />
</label>
<br />
<label>Email: <br />
<Field type="email" name="email" placeholder="Richiesto" />
<ErrorMessage name="email" component="div" />
</label>
<br />
<label>Start and End <br />
<Field type="date" name="start" />
<ErrorMessage name="start" />
<Field type="date" name="end" />
<ErrorMessage name="end" />
</label>
<br />
<label>
Message: <br />
<Field type="text" name="message" />
<ErrorMessage name="message" />
</label>
<br />
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</Form>
)}
</Formik>
</main>
</Layout>
)
export default ContactForm
In the fetch function in onsubmit, it looks like you're sending an object, but the content type is url encoded? Perhaps you need to serialize your object into url encoded format first. There's a host of solutions for that in this question. If you go with the top suggestion:
// https://stackoverflow.com/a/1714899/10340970
const serialize = function(obj) {
var str = [];
for (var p in obj)
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
}
...
fetch("/", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: serialize({
"form-name": "contact",
...values
})
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>
);
}
I already made 2 types of create page:
Create single record.
Import multiple records from xlsx file.
Now I want to implement 2 independent buttons:
Save
Import
meaning that when I click on button 1, only button 1 works.
Here is my code:
<Create {...this.props}>
<TabbedForm toolbar="">
<FormTab label="Single record">
<ReferenceInput label="Centre" source="centre" reference="centre" sort={{ field: 'name', order: 'ASC' }} allowEmpty>
<SelectInput optionText="name" />
</ReferenceInput>
<TextInput source="fullname" />
<TextInput source="serial " />
<TextInput source="birthday" />
<TextInput source="join_date" />
<TextInput source="remark" />
<SaveButton label="Save" redirect="show" submitOnEnter={true} />
</FormTab>
<FormTab label="Import from xlsx">
<ReferenceInput label="Centre" source="centre_import" reference="centre" sort={{ field: 'name', order: 'ASC' }} allowEmpty>
<SelectInput optionText="name" />
</ReferenceInput>
<label id="customLabel">
<input id="upload" ref={(input) => { this.textInput = input; }} type="file" hidden
onClick={(event)=> {
event.target.value = null;
}}
onChange={
(event) => {
this.fileName.textContent = event.target.files[0].name;
}
}
/>
<FlatButton primary label="Select file" icon={<ActionFile />} onClick={() => {
this.textInput.click();
}}/>
<span id="fileName" ref={(span) => { this.fileName = span; }}></span>
</label>
<SaveButton label="Import" redirect={false} submitOnEnter={true} />
</FormTab>
</TabbedForm>
</Create>
The easiest way would be to keep a single button here. You may add a text inside the importation tab explaining that clicking on save will import the file.
However, you still have to deal with the redirection. To do so, you'll have to implement a custom SaveButton:
Copy the code of the default SaveButton into a SaveOrImportButton file.
Update its mapStateToProps function and use redux-form getFormValues selector to inspect the form values and determine whether its an importation.
Use this knowledge to customize the button:
You may update the label to Import if the user selected a file. The label will update immediately after the file field gets dirty.
You can change the redirect value at L22.
Use this button inside a Toolbar component and pass this component to the toolbar prop of the Create component.
How can I normalize the value of the redux-form field when onBlur is triggered. I tried the following, but it didn't seem to work:
const normalizeAmount = (node) => {
const newValue = node.target.value;
return `--${newValue}--`;
};
render() {
const { handleSubmit, pristine, invalid, submitting, error, blur } = this.props;
return (
<form onSubmit={handleSubmit(submit)}>
<div name="form-container">
<Field
name="foo"
component={CustomInput}
onBlur={blurValue => blur(normalizeValue(blurValue))}
/>
...
);
Solved this by moving onBlur to CustomInput component, where I add
return (
<div>
<input
...
onBlur={value => props.input.onBlur(normalizeValue(value))}
/>
</div>
);
And in the form component the field will just have:
<Field
name="foo"
component={CustomInput}
/>
actually normalize is used before any changing in field so it's used before onBlur event, but you are trying to use it in wrong way.
You can use something like this and to allow user to enter only numbers:
<Field component={TextInputField}
onBlur={value => this.doWhatEverYouNeed(value)}
normalize={value => value.replace(/[^\d]/g, '')}
/>
More details about normalize you can find on https://redux-form.com/8.2.2/examples/normalizing/
I notice in a textarea field, sync-error handling doesn't behave like an input field. For example, after displaying a sync-error on a form's input field the error happily disappears when I start typing in the field. On a textarea field, the sync-error just sits there when I start typing (or when I leave the field).
Basically, onBlur is not setting touched to true when I exit the field.
What extra things should I consider when dealing with sync-error handling on a textarea field in a Redux form?
redux-form ^6.x.x changed a lot of its implementation compared to v4 and v5
If you post you sample code, I can help you better though.
I think what u meant, normal field works fine but field
That means your reduxForm(...) works fine, there might be the problem in your error handler function or field rendering function.
I leave simple code example
// validate
const validate = (values) => {
const errors = {};
if(!values.title) {
errors.title = 'title require';
}
if (!values.categories) {
errors.categories = 'categories require';
}
if (!values.content) {
errors.content = 'content require';
}
return errors;
};
// renderField
const renderField = ({ input, label, type, textarea, meta: { touched, error, warning, invalid } }) => {
const textareaType = <textarea {...input} placeholder={label} type={type} className={`form-control ${touched && invalid ? 'has-danger' : ''}`}/>;
const inputType = <input {...input} placeholder={label} type={type} className={`form-control ${touched && invalid ? 'has-danger' : ''}`}/>;
return (
<div>
<label>{label}</label>
<div>
{textarea ? textareaType : inputType}
{touched && ((error && <span>{error}</span>) || (warning && <span>{warning}</span>))}
</div>
</div>
);
};
// React render
<form onSubmit={handleSubmit}>
<Field name="title" component={renderField} type="text" label="Title" />
<Field name="categories" component={renderField} type="text" label="Categories" />
<Field name="content" component={renderField} type="text" label="Content" textarea={true} />
<button type="submit" disabled={pristine || submitting} className="btn btn-primary">Submit</button>
</form>
reduxForm({
form: 'TestComponent', // Name of the form
validate // <--- validation function given to redux-form
})(TestComponent)