Facing a problem while Handle an input with React hooks - javascript

I try to handle the user's text input with hooks.
const [inputValues, setInputValues] = useState({
firstName:"",
lastName:"",
email:"",
telNum:"",
contactType:"Tel.",
message:"",
agree:false
});
and I try to update the values by
const handleChange = event => {
setInputValues({ ...inputValues, [event.target.name]: event.target.value,});
}
and the event:
onChange={handleChange}
Sample input Field code:
<FormGroup row>
<Label htmlFor='firstname' md={2}>
First Name
</Label>
<Col md={10}>
<Input
type='text'
id='firstname'
name='firstname'
placeholder='First Name'
value={firstName}
valid={errors.firstName === ""}
invalid={errors.firstName !== ""}
onBlur={handleBlur("firstName")}
onChange={handleChange} />
<FormFeedback>{errors.firstName}</FormFeedback>
</Col>
</FormGroup>
But whenever I typed something in the input field. I Can't find the value that I entered un the input field.
I didn't understand what happened here. Please Help me to get out from this

There is a typo error in your code. name property is firstName not firstname.
<FormGroup row>
<Label htmlFor='firstname' md={2}>
First Name
</Label>
<Col md={10}>
<Input
type='text'
id='firstname'
name='firstName'
placeholder='First Name'
value={inputValues.firstName}
valid={errors.firstName === ""}
invalid={errors.firstName !== ""}
onBlur={handleBlur("firstName")}
onChange={handleChange} />
<FormFeedback>{errors.firstName}</FormFeedback>
</Col>
</FormGroup>

replace value to value={inputValues. firstName}

Related

How to push all the selected values of checkbox in an array in React-Bootstrap

I am using a react-bootstrap component Checkbox to create a general form . The component name is AdminPage, I wanted tp pass all the selected values of the checkboxes into an state (which is initialised as a state ). I am unable to do so.
Here below is the code
import React, { useState } from "react";
import { Button, Row, Col, Dropdown, Form } from "react-bootstrap";
export const AdminPage = () => {
const [name, setName] = useState('');
const [operations, setOperation] = useState([]);
const handleSubmit = () => {
alert("Selected Checkboxes -" + operations);
}
return (
<>
<div className="p-3 border border-dark bg-light ">
<h3 className="text-center">Add Roles Here</h3>
<Form className="p-3">
<Form.Group as={Row} className="mb-3" controlId="formBasicText">
<Form.Label column sm="3">
Name
</Form.Label>
<Col sm="9">
<Form.Control type="text" value={name} onChange={(e) => setName(e.target.value)} placeholder="Enter Name here..." />
</Col>
</Form.Group>
<Form.Group as={Row} className="mb-3" controlId="formBasicText">
<Form.Label column sm="3">
Opeations
</Form.Label>
{/* <Col sm="9">
<Form.Control type="text" value={rolecredentials.operations} onChange={(e) => onChange(e, "operations")} placeholder='Eg: GETitems, GETstocks, GETpinfences, GETinventory, ADDinventory' />
<Form.Text className="text-muted mx-2">
Mention multiple values using comma seperator like given in placeholder
</Form.Text>
</Col> */}
<Col sm="8">
<Form value={operations} >
<div key={`inline-checkbox`} className="mb-3">
<Form.Check
inline
label="GETitem"
name="group1"
type="checkbox"
value="GETitem"
id={`inline-checkbox-1`}
/>
<Form.Check
inline
label="GETstocks"
name="group1"
type="checkbox"
value="GETstocks"
id={`inline-checkbox-2`}
/>
<Form.Check
inline
label="GETpinfences"
name="group1"
type="checkbox"
value="GETpinfences"
id={`inline-checkbox-3`}
/>
<Form.Check
inline
label="GETinventory"
name="group1"
type="checkbox"
value="GETinventory"
id={`inline-checkbox-4`}
/>
<Form.Check
inline
label="ADDinventory"
name="group1"
type="checkbox"
value="ADDinventory"
id={`inline-checkbox-5`}
/>
</div>
</Form>
</Col>
</Form.Group>
<div className="w-25 m-auto mt-5 mb-3">
<Button variant="primary" type="submit" onClick={handleSubmit}>
Add Role
</Button>
</div>
</Form>
</div>
</>
)
}
I had tried onSelect but still not able to do so.
Have you given the :checked pseudo selector a try?
const checkedElements = document.querySelectorAll(":checked");
Edit
Oh, and the event you're looking for is onChange.
Edit*
const handleSubmit = () => {
alert("Selected Checkboxes -" + operations);
const checkedElements = documents.querySelectorAll(":checked");
checkedElements.forEach((entry) => {
/*Here we have access to each checked element.
*So maybe define an array, push each value you want to that array
*and finally update the state after the forEach.
*/
});
}

this.setState not updating

I'm trying to take the inputs using a form and update the state when the checkbox is clicked but for some reason, the state doesn't update. It doesn't throw any error. I searched on google for answers but none of them were plausible.
My code:
class PatientForm extends React.Component{
constructor(){
super();
this.state={
patientName: "",
age: null,
sex: "",
email: "",
phoneNo: null
}
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit = (event) => {
console.log(this.state);
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
alert(this.state.patientName);
console.log(this.state);
}
render(){
return (
<div className="container-fluid">
<Jumbotron>
<h3 className="display-5">Enter Patient info</h3>
<Form>
<Form.Text className="text-muted">
We'll never share your details with anyone else.
</Form.Text>
<Form.Row>
<Col>
<Form.Control name="patientName" type="text" placeholder="Patient name" required/>
</Col>
<Col>
<Form.Control name="age" type="number" placeholder="Patient Age" required/>
</Col>
<Col>
<Form.Control name="sex" type="text" placeholder="Patient Sex" required/>
</Col>
</Form.Row>
<br />
<Form.Group>
<Form.Control name="email" type="email" placeholder="Enter email" required/>
</Form.Group>
<Form.Group>
<Form.Control name="phoneNo" type="number" placeholder="Phone number" required/>
</Form.Group>
<Form.File />
<Form.Label>Patient's Eth Address</Form.Label>
<Form.Text className="text-muted">
################
</Form.Text>
<Form.Group >
<Form.Check
type="checkbox"
label="Tick if the entered info is correct"
onClick = {this.handleSubmit}
/>
</Form.Group>
<Button variant="primary" type="submit" onClick={ () => console.log(this.state)}>
Submit
</Button>
</Form>
<p>{this.state.patientName}</p>
</Jumbotron>
</div>
)
}
}
export default PatientForm;
Here the handleSubmit function is revoked when the checkbox is clicked.
You need to attach the handleSubmit function to onChange event of every <Form.Control /> you want to use to update the state properties.
Read the "Handling Multiple Inputs" documentation page for more insights.
Here is how you should write you <PatientForm /> (I renamed handleSubmit to handleChange and provide new implementation of handleSumbit):
class PatientForm extends React.Component {
constructor() {
super();
this.state = {
patientName: "",
age: null,
sex: "",
email: "",
phoneNo: null
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleSubmit(event) {
// e.g.: send to remote API
event.preventDefault();
console.log("state", this.state);
console.log("data sent to remote API");
}
render() {
return (
<div className="container-fluid">
<Jumbotron>
<h3 className="display-5">Enter Patient info</h3>
<Form>
<Form.Text className="text-muted">
We'll never share your details with anyone else.
</Form.Text>
<Form.Row>
<Col>
<Form.Control
name="patientName"
type="text"
placeholder="Patient name"
onChange={this.handleChange}
required
/>
</Col>
<Col>
<Form.Control
name="age"
type="number"
placeholder="Patient Age"
onChange={this.handleChange}
required
/>
</Col>
<Col>
<Form.Control
name="sex"
type="text"
placeholder="Patient Sex"
onChange={this.handleChange}
required
/>
</Col>
</Form.Row>
<br />
<Form.Group>
<Form.Control
name="email"
type="email"
placeholder="Enter email"
onChange={this.handleChange}
required
/>
</Form.Group>
<Form.Group>
<Form.Control
name="phoneNo"
type="number"
placeholder="Phone number"
onChange={this.handleChange}
required
/>
</Form.Group>
<Form.File />
<Form.Label>Patient's Eth Address</Form.Label>
<Form.Text className="text-muted">################</Form.Text>
<Form.Group>
<Form.Check
type="checkbox"
label="Tick if the entered info is correct"
/>
</Form.Group>
<Button variant="primary" type="submit" onClick={this.handleSubmit}>
Submit
</Button>
</Form>
<p>{this.state.patientName}</p>
</Jumbotron>
</div>
);
}
}

How do I appropriately handle field change events in React using a custom hook?

I am currently building a simple signup form page to build my knowledge of React Web Apps. I have a number of different types of form elements. I am running into the following error when I use my custom hook to handle changes in any of the form fields that are not simple text fields.
TypeError: Cannot read property 'name' of undefined
(anonymous function)
C:/Users/paris/Desktop/covidsocial/frontend/src/libs/hooksLib.js:11
function(event) {
9 | setValues({
10 | ...fields,
> 11 | [event.target.name]: event.target.value
| ^ 12 | });
13 | }
14 | ];
The above error message occurs anytime i select a country from the region and country selector drop-downs or the date picker. I have tried using both name and control-id elements as the ids but I still get the same error message as above. I think the issue is with how I am setting my values, but I am very new to React and am having trouble pinning down exactly whats going on. Any help would be greatly appreciated!
Here is the relevant code for my Signup.js class as well as the custom react hook
hookslib.js
import { useState } from "react";
export function useFormFields(initialState) {
const [fields, setValues] = useState(initialState);
return [
fields,
function(event) {
setValues({
...fields,
[event.target.name]: event.target.value
});
}
];
}
Signup.js
export default function Signup() {
const [fields, handleFieldChange] = useFormFields({
email: "",
password: "",
confirmPassword: "",
confirmationCode: "",
gender: "",
onList: false,
dateOfBirth: "",
mailingAddressLine1: "",
mailingAddressLine2: "",
mailingAddressCity: "",
mailingAddressState: "",
mailingAddressZip: "",
billingAddressLine1: "",
billingAddressLine2: "",
billingAddressCity: "",
billingAddressState: "",
billingAddressZip: "",
useShippingAsBilling: false,
});
const history = useHistory();
const [newUser, setNewUser] = useState(null);
const { userHasAuthenticated } = useAppContext();
const [isLoading, setIsLoading] = useState(false);
function validateForm() {
return (
fields.email.length > 0 &&
fields.password.length > 0 &&
fields.password === fields.confirmPassword
);
}
function validateConfirmationForm() {
return fields.confirmationCode.length > 0;
}
async function handleSubmit(event) {
event.preventDefault();
setIsLoading(true);
try {
const newUser = await Auth.signUp({
username: fields.email,
password: fields.password,
confirmPassword: fields.confirmPassword,
gender: fields.gender,
firstName: fields.firstName,
lastName: fields.lastName,
onList: fields.onList,
dateOfBirth: fields.dateOfBirth,
mailingAddressLine1: fields.mailingAddressLine1,
mailingAddressLine2: fields.mailingAddressLine2,
mailingAddressCity: fields.mailingAddressCity,
mailingAddressState: fields.mailingAddressState,
mailingAddressZip: fields.mailingAddressZip,
mailingAddressCountry: fields.mailingAddressCountry,
billingAddressCountry: fields.billingAddressCountry,
billingAddressLine1: fields.billingAddressLine1,
billingAddressLine2: fields.billingAddressLine2,
billingAddressCity: fields.billingAddressCity,
billingAddressState: fields.billingAddressState,
billingAddressZip: fields.billingAddressZip,
});
setIsLoading(false);
setNewUser(newUser);
} catch (e) {
onError(e);
setIsLoading(false);
}
}
async function handleConfirmationSubmit(event) {
event.preventDefault();
setIsLoading(true);
try {
await Auth.confirmSignUp(fields.email, fields.confirmationCode);
await Auth.signIn(fields.email, fields.password);
userHasAuthenticated(true);
history.push("/");
} catch (e) {
onError(e);
setIsLoading(false);
}
}
function renderConfirmationForm() {
return (
<form onSubmit={handleConfirmationSubmit}>
<FormGroup controlId="confirmationCode" bsSize="large">
<ControlLabel>Confirmation Code</ControlLabel>
<FormControl
autoFocus
type="tel"
onChange={handleFieldChange}
value={fields.confirmationCode}
/>
<HelpBlock>Please check your email for the code.</HelpBlock>
</FormGroup>
<LoaderButton
block
type="submit"
bsSize="large"
isLoading={isLoading}
disabled={!validateConfirmationForm()}
>
Verify
</LoaderButton>
</form>
);
}
function renderForm() {
return (
<form onSubmit={handleSubmit}>
<FormGroup controlId="email" bsSize="large">
<ControlLabel>Email</ControlLabel>
<FormControl
autoFocus
name = "email"
type="email"
value={fields.email}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup controlId="password" bsSize="large">
<ControlLabel>Password</ControlLabel>
<FormControl
type="password"
name = "password"
value={fields.password}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup controlId="confirmPassword" bsSize="large">
<ControlLabel>Confirm Password</ControlLabel>
<FormControl
type="password"
name = "confirmPassword"
onChange={handleFieldChange}
value={fields.confirmPassword}
/>
</FormGroup>
<FormGroup controlId="mailingAddressLine1" bsSize="large">
<ControlLabel>Mailing Address Line 1</ControlLabel>
<FormControl
type="text"
name = "mailingAddressLine1"
onChange={handleFieldChange}
value={fields.mailingAddressLine1}
/>
</FormGroup>
<FormGroup controlId="mailingAddressLine2" bsSize="large">
<ControlLabel>Mailing Address Line 2</ControlLabel>
<FormControl
type="text"
name = "mailingAddressLine2"
onChange={handleFieldChange}
value={fields.mailingAddressLine2}
/>
</FormGroup>
<FormGroup controlId="mailingAddressCountry" bsSize="large">
<ControlLabel>Country</ControlLabel>
<CountryDropdown
name = "mailingAddressCountry"
country={fields.mailingAddressCountry}
value={fields.mailingAddressCountry}
onChange={handleFieldChange} />
</FormGroup>
<FormGroup controlId="mailingAddressRegion" bsSize="large">
<ControlLabel>State</ControlLabel>
<RegionDropdown
//country={country}
name="mailingAddressRegion"
country={fields.mailingAddressCountry}
value={fields.mailingAddressState}
onChange={handleFieldChange} />
</FormGroup>
<FormGroup controlId="city" bsSize="large">
<ControlLabel>City</ControlLabel>
<FormControl
type="text"
name="city"
onChange={handleFieldChange}
value={fields.mailingAddressCity}
/>
</FormGroup>
<FormGroup controlId="zipCode" bsSize="large">
<ControlLabel>Zip Code</ControlLabel>
<FormControl
type="text"
name="zipCode"
onChange={handleFieldChange}
value={fields.mailingAddressZip}
/>
</FormGroup>
<FormGroup controlId="useShippingAsBilling" bsSize="large">
<label>
Use Shipping As Billing:
<input
name = "useShippingAsBilling"
type="checkbox"
id="useShippingasBilling"
value={fields.useShippingAsBilling}
checked={fields.useShippingAsBilling === true}
onChange={handleFieldChange} />
</label>
</FormGroup>
<br />
<FormGroup controlId="billingAddressLine1" bsSize="large">
<ControlLabel>Billing Address Line 1</ControlLabel>
<FormControl
name ="billingAddressLine1"
type="text"
value={fields.billingAddressLine1}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup controlId="billingAddressLine2" bsSize="large">
<ControlLabel>Billing Address Line 2</ControlLabel>
<FormControl
name ="billingAddressLine2"
type="text"
value={fields.billingAddressLine2}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup controlId="billingAddressCountry" bsSize="large">
<ControlLabel>BillingAddressCountry</ControlLabel>
<CountryDropdown
name="billingAddressCountry"
value={fields.billingAddressCountry}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup controlId="mailingAddressRegion" bsSize="large">
<ControlLabel>Billing Address Region</ControlLabel>
<RegionDropdown
name="mailingAddressRegion"
country={fields.billingAddressCountry}
value={fields.billingAddressRegion}
onChange={handleFieldChange} />
</FormGroup>
<FormGroup controlId="billingCity" bsSize="large">
<ControlLabel>City</ControlLabel>
<FormControl
name = "billingCity"
type="text"
value={fields.billingAddressCity}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup controlId="billingZipCode" bsSize="large">
<ControlLabel>Zip Code</ControlLabel>
<FormControl
name = "billingZipCode"
type="text"
value={fields.billingAddressZip}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup controlId="gender" bsSize="sm">
<ControlLabel>Gender</ControlLabel>
<br></br>
<ControlLabel>Male</ControlLabel>
<FormControl
name = "gender"
type="radio"
onChange={handleFieldChange}
value={fields.gender}
checked={fields.gender === 'male'}
/>
<ControlLabel>Female</ControlLabel>
<FormControl
name = "gender"
type="radio"
onChange={handleFieldChange}
value={fields.gender}
checked={fields.gender === 'female'}
/>
<ControlLabel>Other</ControlLabel>
<FormControl
name = "gender"
type="radio"
onChange={handleFieldChange}
value={fields.gender}
checked={fields.gender === 'other'}
/>
</FormGroup>
<FormGroup controlId="onList" bsSize="sm">
<br></br>
<ControlLabel>Join Email List</ControlLabel>
<br></br>
<ControlLabel>Yes</ControlLabel>
<FormControl
name = "onList"
type="checkbox"
onChange={handleFieldChange}
value={fields.onList}
checked={fields.onList === 'true'}
/>
</FormGroup>
<FormGroup controlId="dateOfBirth">
<ControlLabel>Date of Birth</ControlLabel>
<DatePicker
name="dateOfBirth"
value={fields.dateofBirth}
selected={fields.dateOfBirth}
onChange={handleFieldChange}
locale="en"
/>
</FormGroup>
<FormGroup controlId="content">
<ControlLabel>Notes Area</ControlLabel>
<FormControl
name = "content"
value={fields.content}
componentClass="textarea"
onChange={handleFieldChange}
/>
</FormGroup>
<LoaderButton
block
type="submit"
bsSize="large"
isLoading={isLoading}
disabled={!validateForm()}
>
Signup
</LoaderButton>
</form>
);
}
return (
<div className="Signup">
{newUser === null ? renderForm() : renderConfirmationForm()}
</div>
);
}
This is a clever approach to handling change events and persisting values to state. You do, however, put a lot of faith in this component library to fire onChange events consistently with their HTML counterparts.
I noticed in the docs that the onChange is a little different than you might expect:
<CountryDropdown
value={country}
onChange={(val) => this.selectCountry(val)} />
<RegionDropdown
country={country}
value={region}
onChange={(val) => this.selectRegion(val)} />
Both of these expect an arrow function handler to receive the val property, so you might consider rewriting your implementation:
<CountryDropdown
name = "mailingAddressCountry"
country={fields.mailingAddressCountry}
value={fields.mailingAddressCountry}
onChange={(val) => updateField({ mailingAddress: val})} />
And modify your hook to so that you aren't working from the bare event. It'll require a little more syntax, and there's probably a cleaner way to approach, but it will give you the control you need to handle edge cases. Something like so:
import { useState } from "react";
export function useFormFields(initialState) {
const [fields, setValues] = useState(initialState);
return [
fields,
function(value) {
setValues({
...fields,
...value
});
}
];
}

How to edit a Form in Redux?

I am new to Redux. I've learned React and trying to learn Redux. I am building a todo app with Redux. I am managed to create, read and delete todos, but I am not managed to edit the todo.
My code: AddTodoForm
<FormGroup>
<Label for="title">Title</Label>
<Input type="text" name="title" id="title" placeholder="Enter Title" onChange={this.handleChange.bind(this)} /> {/* <input type="text" value={this.state.value} onChange={this.handleChange.bind(this, 'title')} /> */}
</FormGroup>
<FormGroup>
<Label for="description">Description </Label>
<Input type="textarea" name="description" id="description" onChange={this.handleChange.bind(this)} />
</FormGroup>
<FormGroup>
<div>
<CustomInput className="toggleInput" type="checkbox" data-toggle="toggle" id="exampleCustomCheckbox" label="Do You want to add Reminder??" onChange={this.toggle.bind(this, !this.state.checkBoxToggle)} />
</div>
</FormGroup>
{this.state.checkBoxToggle ?
<FormGroup>
<Label for="reminder">Reminder </Label>
<Input type="datetime-local" name="date" defaultValue={moment(Date.now()).format( 'YYYY-MM-DDTHH:mm')} id="date" onChange={this.handleChange.bind(this)} />
</FormGroup>
: ''}
<FormGroup check row>
<Col className="text-center">
<Button className="btn btn-success" onClick={this.handleSubmit.bind(this)}>Submit</Button>
</Col>
</FormGroup>
My handleChange function, where I set states of input:
handleChange(e) {
console.log(e.target.value, e.target.name);
if (e.target.name == "date") {
console.log('date is', e.target.value, new Date(e.target.value).valueOf());
this.setState({
[e.target.name]: new Date(e.target.value).valueOf()
})
} else {
this.setState({
[e.target.name]: e.target.value
})
}
}
This the render list function, where I want to edit my todo, but I am not able to edit the todo. I am able to delete, but not edit:
renderList() {
if (this.props.todos) {
return _.map(this.props.todos, (todo, id) => {
return (
<tr key={id + 1}>
<th scope="row">{id + 1}</th>
<td><Input type="text" disabled name="title" id="title" value={todo.title} onChange={this.handleChange.bind(this)} /></td>
<td><Input type="textarea" value={todo.description ? todo.description : this.state.description} name="description" id="description" onChange={this.handleChange.bind(this)} /></td>
<td>{todo.reminder}</td>
<td> <button className='btn btn-danger' onClick={this.onDeleteClick.bind(this, todo._id)}>Delete</button></td>
<td><button className='btn btn-success' onClick={this.markCompleted.bind(this, todo._id)}>Mark Complete</button></td>
</tr>
);
})
}
}
The specific todo, which I want to edit doesn't allow to type any value in the input box. I am not able to set it. Please let me know where I am doing wrong.
Don't reinvent the wheel. Instead of trying to reimplement form state, with event handlers, slice and reducers, use Redux Form.
It is made for that specific purpose and has an elegant, efficient API.

Redux Form - populating initial values

I am trying to populate a form with initial data however I am unsure of the syntax for this functionality and how it's suppose to be applied. initially the form I am using is a component that I also use to create a client. I am trying to reuse this form as the form for editing a client. It has two functions.
As per suggestions in Redux I have a this as a component and I also have a container.
Now, using the redux tool in Chrome I can look at the state and its clear the action has added an "editClient" entry with data so I do have the data. Its called "editClient" in the state.
My problem is that I do not know how to use this to set these state values as initial values. I have looked carefully at the docs but I am confused as to the way it should be stuctured.
Here is my client form in its entirety:
import React, { PropTypes } from 'react'
import { Field, reduxForm, FormSection } from 'redux-form'
import { connect } from 'react-redux'
import { Col, Row } from 'react-bootstrap'
import { Button, Glyphicon, Panel } from 'react-bootstrap'
import Moment from 'moment'
import Address from '../../address/addressContainer'
import FormField from '../../formComponents/formField'
import CheckboxField from '../../formComponents/checkboxField'
import TextField from '../../formComponents/textField'
import StaticText from '../../formComponents/staticText'
import TextAreaField from '../../formComponents/textAreaField'
import DateField from '../../formComponents/datefield'
import reducer from '../edit/reducer'
export const CLIENT_FORM_NAME = 'Client'
const required = value => (value ? undefined : 'Required')
const maxLength = max => value =>
value && value.length > max ? `Must be ${max} characters or less` : undefined
const number = value =>
value && isNaN(Number(value)) ? 'Must be a number' : undefined
const minValue = min => value =>
value && value < min ? `Must be at least ${min}` : undefined
const email = value =>
value && !/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value)
? 'Invalid email address'
: undefined
const tooOld = value =>
value && value > 65 ? 'You might be too old for this' : undefined
const aol = value =>
value && /.+#aol\.com/.test(value)
? 'Really? You still use AOL for your email?'
: undefined
const normalizeMobilePhone = value => {
if (!value) {
return value
}
const onlyNums = value.replace(/[^\d]/g, '')
if (onlyNums.length <= 4) {
return onlyNums
}
if (onlyNums.length <= 8) {
return `${onlyNums.slice(0, 4)} ${onlyNums.slice(4)}`
}
return `${onlyNums.slice(0, 4)} ${onlyNums.slice(4, 7)} ${onlyNums.slice(7, 10)}`
}
export const Client = (props) => {
const {
handleSubmit,
companyValue,
isWarrantyCompanyValue,
isEditMode } = props
const { reset } = props
return (
<Row>
<Col md={12}>
<h2><Glyphicon glyph="edit" /> {isEditMode ? 'Edit' : 'New'} Client</h2>
<hr />
<form onSubmit={handleSubmit} className="form-horizontal">
{isEditMode && (
<Panel header={<h3>Client - Basic Details</h3>}>
<Row>
<Field component={StaticText}
name="clientNo"
id="clientNo"
label="Client No."
fieldCols={4}
labelCols={4}
controlCols={8}
/>
<Field component={StaticText}
name="dateCreated"
id="dateCreated"
label="Date Created."
fieldCols={4}
labelCols={4}
controlCols={8}
/>
<Field component={StaticText}
name="userName"
id="userName"
label="Created By."
fieldCols={4}
labelCols={4}
controlCols={8}
/>
</Row>
<Row>
<Field
component={props => {
return (
<StaticText {...props}>
<p
className="form-control-static"
>
<Glyphicon glyph={props.input.value ? 'ok' : 'remove'} />
{' '}{props.input.value ? 'Has jobs attached' : 'No jobs attached'}
</p>
</StaticText>
)
}}
name="activity"
id="activity"
label="Activity"
fieldCols={4}
labelCols={4}
controlCols={8}
/>
<Field component={CheckboxField}
name="active"
id="active"
label="De-Activate"
checkboxLabel="De activate this client"
fieldCols={4}
labelCols={4}
controlCols={8}
/>
</Row>
</Panel>
)}
<Panel header={<h3>Client - CompanyDetails</h3>}>
<Row>
<Field component={CheckboxField}
id="company"
name="company"
label="Company?"
checkboxLabel="Client represents a company"
fieldCols={6}
labelCols={3}
controlCols={9}
/>
</Row>
{companyValue && (
<div>
<Row>
<Field component={TextField}
name="companyName"
id="companyName"
type="text"
label="Company Name"
placeholder="Enter company name..."
fieldCols={6}
labelCols={3}
controlCols={9}
/>
<Field component={TextField}
name="abn"
id="abn"
type="text"
label="ABN."
fieldCols={6}
labelCols={3}
controlCols={5}
/>
</Row>
<Row>
<Field component={CheckboxField}
id="isWarrantyCompany"
name="isWarrantyCompany"
label="Warranty Company?"
checkboxLabel="Client represents a warranty company"
fieldCols={6}
labelCols={3}
controlCols={9}
/>
{isWarrantyCompanyValue && (
<Field component={CheckboxField}
id="requiresPartsPayment"
name="requiresPartsPayment"
label="Requires Parts Payment?"
checkboxLabel="We pay for parts"
fieldCols={6}
labelCols={3}
controlCols={9}
/>
)}
</Row>
<Row>
<Field component={TextField}
name="companyEmail"
id="companyEmail"
type="email"
label="Spare Parts Email."
placeholder="Enter spare parts email..."
fieldCols={6}
labelCols={3}
controlCols={9}
/>
</Row>
</div>
)}
</Panel>
<Panel header={<h3>Client - {companyValue ? 'Company Contact' : 'Personal'} Details</h3>}>
<Row>
<Field component={TextField}
name="clientFirstName"
id="clientFirstName"
type="text"
label="First Name."
placeholder="Enter first name..."
fieldCols={6}
labelCols={3}
controlCols={9}
validate={[required]}
/>
<Field component={TextField}
name="clientLastName"
id="clientLastName"
type="text"
label="Last Name."
placeholder="Enter last name..."
fieldCols={6}
labelCols={3}
controlCols={9}
/>
</Row>
<Row>
<Field component={TextField}
name="mobilePhone"
id="mobilePhone"
type="text"
label="Mobile No."
placeholder="Enter mobile No..."
fieldCols={6}
labelCols={3}
controlCols={5}
normalize={normalizeMobilePhone}
/>
<Field component={TextField}
name="phone"
id="phone"
type="text"
label="Phone No."
placeholder="Enter phone No..."
fieldCols={6}
labelCols={3}
controlCols={5}
/>
</Row>
<Row>
<Field component={TextField}
name="email"
id="email"
type="email"
label="Email."
placeholder="Enter email address..."
fieldCols={6}
labelCols={3}
controlCols={9}
/>
</Row>
</Panel>
<FormSection name="Address">
<Address />
</FormSection>
<Panel header={<h3>Notes</h3>}>
<Row>
<Field component={TextAreaField}
id="notes"
name="notes"
label="Notes."
placeholder="Enter notes here..."
fieldCols={12}
labelCols={1}
controlCols={11}
/>
</Row>
</Panel>
<Panel header={<h3>Client - Bank Details</h3>}>
<Row>
<Field component={TextField}
name="bankName"
id="bankName"
type="text"
label="Bank Name."
placeholder="Enter bank name..."
fieldCols={4}
labelCols={4}
controlCols={8}
/>
<Field component={TextField}
name="bsb"
id="bsb"
type="text"
label="BSB No."
placeholder="Enter BSB No..."
fieldCols={4}
labelCols={4}
controlCols={8}
/>
<Field component={TextField}
name="account"
id="account"
type="text"
label="Account No."
placeholder="Enter Account No..."
fieldCols={4}
labelCols={4}
controlCols={8}
/>
</Row>
</Panel>
<div className="panel-body">
<Row>
<Col xs={4}>
<Row>
<Col xs={8} xsOffset={4}>
<Button bsStyle="primary" type="submit" bsSize="small">
<Glyphicon glyph="ok" /> Submit
</Button>
{' '}
<Button type="reset" bsSize="small" onClick={reset}>
<Glyphicon glyph="ban-circle" /> Clear
</Button>
</Col>
</Row>
</Col>
</Row>
</div>
</form>
</Col>
</Row >
)
}
let ClientForm = reduxForm({
form: CLIENT_FORM_NAME,
})(Client)
ClientForm = connect(
state => ({
initialValues: state.editClient // pull initial values from client reducer
}),
{ reducer } // bind client loading action creator
)(Client)
export default ClientForm
I have added the following at the bottom as per the redux form example:
ClientForm = connect(
state => ({
initialValues: state.editClient // pull initial values from client reducer
}),
{ reducer } // bind client loading action creator
)(Client)
...wnd when I save it I get the following error.
Exception: Call to Node module failed with error: Error: Field must be inside a component decorated with reduxForm()
I believe I have not understood how to set the initial values.
Where have I gone wrong and what I need to do to make this take the state values and load them?
The parameter for the function that connect returns should be ClientForm instead of Client. Try this:
ClientForm = connect(
state => ({
initialValues: state.editClient // pull initial values from client reducer
}),
{ reducer } // bind client loading action creator
)(ClientForm)

Categories

Resources