Cannot focus on first error input in Formik - reactjs

I have the following implementation of a formik component that renders a form,
I am trying to access the first error field so I can focus on it but with no avail, i will show code
const CompanyProfile = () => {
const CompanySchema = Yup.object().shape({
name: Yup.string()
.min(2, 'too short')
.required(ERROR_REQUIRED),
industry: Yup.string().notRequired(),
address: Yup.string().notRequired(),
crn: Yup.number().required(ERROR_REQUIRED),
website: Yup.string()
.notRequired()
.min(2, 'too short'),
employeesNbr: Yup.string().required(ERROR_REQUIRED),
phoneNumber: Yup.string().required(ERROR_REQUIRED),
userRole: Yup.string().required(ERROR_REQUIRED),
personCheck: Yup.boolean().required(ERROR_REQUIRED),
});
const registerCompany = async values => {
try {
const data = values;
delete data.personCheck;
await addCompany(data);
} catch (error) {
console.log(error);
}
};
const successSubmit = values => {
registerCompany(values);
};
const forSubmit = formik => {
console.log('not valid');
const { errors } = formik;
const keys = Object.keys(errors);
console.log(formik);
if (keys.length > 0) {
const selector = `[id="${keys[0]}"]`;
const errorElement = document.getElementsByName(selector);
errorElement.focus();
}
};
const formik = useFormik({
initialTouched: false,
validateOnChange: true,
validateOnBlur: true,
initialValues: {
name: '',
industry: '',
address: '',
crn: '',
website: '',
employeesNbr: '',
phoneNumber: '',
userRole: '',
personCheck: false,
},
validationSchema: CompanySchema,
onSubmit: values => {
successSubmit(values);
},
handleSubmit: formik => {
forSubmit(formik);
},
});
return (
<Skeleton pageTitle={PAGE_TITLE_COMPANY_PROFILE}>
<CompanyProfileForm formik={formik} />
</Skeleton>
);
};
export default connect(CompanyProfile);
I dont know where I am going wrong, I attached the name,value, onchange correctly in the input fields because I am able to extract the values
Thank you

Related

Form handling using Formik library in react js

I want to handle three form in single component with suitable initialValues and Schemas, since I'm using formik and yup for form handling and validation. (is it okay to do such practice?)
const initialValuesLogin = { name: '', email: '', password: '' };
const initialValuesBookTable = {
name: '',
date: '',
time: '',
contact: '',
details: '',
};
const initialValuesRegister = {
name: '',
email: '',
password: '',
confirm_password: '',
};
const [register, setRegister] = useState(true);
`this State is used to handle the toggle between login-form and register-form`;
const [username, setUsername] = useState('');
const { values, errors, handleBlur, handleChange, handleSubmit, touched } =
useFormik({
initialValues:
props.show === 'loginForm'
? register
? initialValuesRegister
: initialValuesLogin
: initialValuesBookTable,
validationSchema:
props.show === 'loginForm'
? register
? registerSchema
: loginSchema
: bookTableSchema,
onSubmit: (values, action) => {
action.resetForm();
setUsername(values.name);
},
});
I tried to handle three different forms in single component so basically there are 3 forms as- login, register and booktable. I've created different initialValues for all of them as well as schemas, and I've used multiple ternary operators but the issue is when I submit form for login it takes initialvalues of registered form but I just want that it should take values as per selected forms like(for 'login' it takes 'initialValuesLogin' and similarly for 'register' it takes 'initialValuesRegister') Btw it works fine for booktable form !!
I'm using multiple form submissions in same components like below.
const loginValidation = Yup.object({ });
const loginFormik = useFormik({
initialValues: loginInitialValue ,
validateOnChange: false,
validateOnBlur: true,
validationSchema: loginValidation ,
onSubmit: (values) => {}
});
const registerValidation = Yup.object({ });
const registerFormik = useFormik({
initialValues: registerInitialValue ,
validateOnChange: false,
validateOnBlur: true,
validationSchema: registerValidation ,
onSubmit: (values) => {}
});
const booktableValidation = Yup.object({ });
const booktableFormik = useFormik({
initialValues: booktableInitialValue ,
validateOnChange: false,
validateOnBlur: true,
validationSchema: booktableValidation ,
onSubmit: (values) => {}
});

DraftJS createWithContent returns undefined reading 'getBlockMap'

I am using draftjs to update data from a server call. I am using MongoDB as the database and graphql as the query language. I can convert the data from the API using convertFromRaw(JSON.parse(data)) . I then set it to state, but when I attempt to createWithContent() i get an error Cannot read properties of undefined (reading 'getBlockMap'). My code is below. Been working on this for two days.
const GET_ISP_ENTRY = gql`
query IspListEntry($ispListEntryId: ID!) {
ispListEntry(id: $ispListEntryId) {
_id
displayName
contactFirstName
contactLastName
contactTitle
lastUpdated
onlineService
onlineAttn
address
city
state
zipCode
country
phoneNumber
extension
mobileNumber
faxNumber
email
website
referTo
notes
previous
}
}
`;
const UPDATE_ISP_ENTRY = gql`
mutation UpdateISPEntry($ispListEntryUpdateId: ID!, $input: UpdateISPEntry) {
ispListEntryUpdate(id: $ispListEntryUpdateId, input: $input) {
displayName
}
}
`;
const UpdateISPEntry = () => {
const ispEntryFields = {
displayName: '',
lastUpdated: Date(),
onlineService: '',
contactTitle: '',
contactFirstName: '',
contactLastName: '',
onlineAttn: '',
address: '',
city: '',
state: '',
zipCode: '',
country: '',
phoneNumber: '',
extension: '',
mobileNumber: '',
faxNumber: '',
email: '',
website: '',
referTo: '',
notes: '',
previous: ''
};
const [rawNotesFromDB, setRawNotesFromDB] = useState();
const [urlId, setUrlId] = useState('');
const [getIsp, { data, loading, error }] = useLazyQuery(GET_ISP_ENTRY, {
variables: {
ispListEntryId: urlId
},
onCompleted: () => {
loading
? console.log('Loading....')
: setEditorNotesState(
convertFromRaw(JSON.parse(data.ispListEntry.notes))
);
},
onError: () => {
toast.error(error);
}
});
const [editorNotesState, setEditorNotesState] = useState(() =>
EditorState.createWithContent().getCurrentContent()
);
console.log(editorNotesState);
const [formValues, setFormValues] = useState();
const [previousValue, setPreviousValue] = useState();
const [editorPreviousState, setEditorPreviousState] = useState();
const [
submitValues,
{ data: successful, loading: successLoading, error: loadingError }
] = useMutation(UPDATE_ISP_ENTRY, {
onError: () => {
toast.error(`There was an error ${loadingError}`);
}
});
const params = useLocation();
const path = params.pathname;
const pathSplit = path.split('/')[2];
useEffect(() => {
getIsp();
setFormValues(data && data.ispListEntry);
setUrlId(pathSplit);
}, [data, getIsp, pathSplit, formValues]);
// const convertedState = convertFromRaw(
// JSON.parse(data && data.ispListEntry.notes)
// );
// console.log(convertedState);
// const raw = () => {
// !formValues
// ? console.log('DAMN')
// : setRawNotes(convertFromRaw(JSON.parse(formValues.notes)));
// };
const handleSubmit = () => {};
return (
<Fragment>
<div className='container p-4 parent-container'>
<ISPFormHeader />
<ISPFormHeaderPagename children='Update ISP Entry' />
<ISPForm
initialValues={data && data.ispListEntry}
enableReinitialize={true}
onSubmit={handleSubmit}
/>
<div className='editor-fields'>
<div className='rt-editor'>
<header className='rt-editor-header'>Notes</header>
<EditorComponent
id='notes'
name='notes'
type='text'
editorState={editorNotesState}
onEditorStateChange={setEditorNotesState}
/>
</div>
<div className='rt-editor'>
<header className='rt-editor-header'>Previous</header>
<EditorComponent
name='previous'
id='previous'
type='text'
EditorState={editorPreviousState}
// onEditorStateChange={handleEditorPreviousChange}
/>
</div>
</div>
</div>
</Fragment>
);
};
export default UpdateISPEntry;

Why state show undefined?

I am working on form validation and I make two arrays one for check value and the second was check validation but when the page refresh and render then in my console log show undefined in my name state. whether I give him to a true value in the state. Does anyone have any idea why is this?
var validation = [{
name: true,
company: true,
email: true,
phone: true,
message: true,
}]
const [isValidate, setisValidate] = React.useState({ ...validation })
const [error, seterror] = React.useState({
name: '',
company: '',
email: '',
phone: '',
message: '',
});
const isValidFun = (param) => {
let isTrue = true;
if((param === "name" || param === "all") && (!error.name || error.name.length < 5)) {
isValidate.name = false;
isTrue = false;
} else {
isValidate.name = true;
}
setisValidate({ ...isValidate })
return isTrue;
}
const handleChange = (e) => {
error[e.target.name] = e.target.value;
seterror({ ...error });
isValidFun(e.target.name);
};
console.log(isValidate.name)
const sentMail = () => {
let isValid = isValidFun("all");
if (isValid) {
alert('Form submitted')
}
};
return (
<Input
type="text"
name="name"
placeholder="Name"
value={error.name}
onChange={handleChange}
/>
{!isValidate.name && <p className="error">This field is required</p>}
);
};
Your validation object is an array. When you initialise the state, you use the spread operator on the array inside the object, so you end up with an object with key 0 and value of the object.
var validation = [{
name: true,
company: true,
email: true,
phone: true,
message: true,
}]
console.log({...validation}]
Instead, change the validation to an object and assign it to state.
var validation = {
name: true,
company: true,
email: true,
phone: true,
message: true,
}
const [isValidate, setisValidate] = React.useState(validation);
Should be the spreader. validation variable should be like this
var validation = {
name: true,
company: true,
email: true,
phone: true,
message: true,
}

Cannot read property 'files' of undefined for sending multiple images

Code
class Add_Give_Item_Form extends Component {
constructor(props) {
super(props);
this.state = {
// #インプット情報用
info: {
name: '',
owner: '',
keyword1: '',
keyword2: '',
keyword3: '',
bland: '',
state: '未使用、新品',
category: '',
images: [],
detail: '',
},
// Validation用
//  urlは必須項目ではないのでValidationには含めない
message: {
name: '',
keyword1: '',
keyword2: '',
keyword3: '',
state: '',
category: '',
detail: '',
},
allCategory: null,
allBland: null,
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleImageSelect = this.handleImageSelect(this);
}
////
...
////
handleChange = (e) => {
const name = e.target.name;
const value = e.target.value;
const { info, message } = this.state;
this.setState({
info: { ...info, [name]: value },
});
this.setState({
message: { ...message, [name]: this.validator(name, value) },
});
};
handleImageSelect = (e) => {
this.setState({
info: { ...this.state.info, images: [...this.state.info.images, e.target.files] },
});
};
render() {
const { info, message, allCategory, allBland } = this.state;
// setStateが完了するまではnullにする。
if (this.state.allCategory === null || this.state.allBland === null) {
return <CircularProgress />;
} else {
return (
<div>
///////
.....
///////
<label>Images</label>
<input type="file" multiple onChange={this.handleImageSelect} />
What I want to do
I would like to catch each file sent by a user and put into state as this.state.info.images which is an array.
I saw some questions on stackoverflow and then I found some solutions. When I wrote the same code as what I saw, I got an error like below.
cannot read property files of undefined
I should write the same code but I got the error for some reasons.
I may take another way to realize what I want to do, but I want to write readable codes and figure out why it is happening.
I would like you to teach me why this happens and solutions.
Thank you very much.
I just notice I didn't put bind with this.handleImageSelect = this.handleImageSelect(this).
Now it works well.
Thank you very much.

Checkbox value in React and MongoDB

What I am seeking to accomplish is to have an optional checkbox in a form that returns false when unchecked and true when checked (in the DB).
However, whenever I view my submission in the console, things appear to be find - just not showing up in Mongo. I have attempted numerous things after searching all day both frontend and backend schema. Any help or insight would be much appreciated.
export default class CreateworkOrder extends Component {
constructor(props) {
super(props);
this.onChangeEmployee = this.onChangeEmployee.bind(this);
this.onChangeDescription = this.onChangeDescription.bind(this);
this.onChangeDuration = this.onChangeDuration.bind(this);
this.onChangeDate = this.onChangeDate.bind(this);
this.handleCheckClick = this.handleCheckClick.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
employee: '',
description: '',
duration: 0,
date: new Date(),
employees: [],
isComplete: false
}
}
componentDidMount() {
axios.get('http://localhost:5000/employees/')
.then(response => {
if (response.data.length > 0) {
this.setState({
employees: response.data.map(emp => emp.employee),
employee: response.data[0].employee
})
}
})
.catch((error) => {
console.log(error);
})
}
handleCheckClick = () => {
const complete = !this.state.isComplete;
console.log(complete);
this.setState({ complete: !this.state.isComplete});
}
Then submit below:
onSubmit(e) {
e.preventDefault();
const workOrder = {
employee: this.state.employee,
description: this.state.description,
duration: this.state.duration,
date: this.state.date,
isComplete: this.state.isComplete
}
console.log(workOrder);
axios.post('http://localhost:5000/workOrders/add', workOrder)
.then(res => console.log(res.data)).catch(console.error);
//window.location = '/home';
}
portion of the form to optionally select
<div className="form-group">
<label>Only check box if job has been completed </label>
<input name="isComplete" type="checkbox"
defaultChecked={this.state.isComplete}
onChange={this.handleCheckClick}
className="filled-in" id="filled-in-box"/>
</div>
<div className="form-group">
<input type="submit" value="Create WO" className="btn btn-primary" onSubmit={this.onSubmit}/>
</div>
</form>
DB Model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const workorderSchema = new Schema({
employee: { type: String, required: true },
description: { type: String, required: true },
duration: { type: Number, required: true },
date: { type: Date, required: true },
isComplete: { type: Boolean, required: false },
},
{
timestamps: true,
});
const WorkOrder = mongoose.model('WorkOrder', workorderSchema);
module.exports = WorkOrder;
but console does show true
You are using the state variable isComplete but setting the state in complete.
this.state = {
employee: '',
description: '',
duration: 0,
date: new Date(),
employees: [],
isComplete: false
}
In handleCheckClick you are doing:
handleCheckClick = () => {
const complete = !this.state.isComplete;
console.log(complete);
this.setState({ complete: !this.state.isComplete}); }
And you are submitting workOrder which is using isComplete, which you didn't change
const workOrder = { employee: this.state.employee, description:
this.state.description, duration: this.state.duration, date:
this.state.date, isComplete: this.state.isComplete }
This should be the reason. So change the handleCheckClick like this:
handleCheckClick = () => {
let complete = !this.state.isComplete;
console.log(complete);
this.setState({ isComplete: complete});
}
Also, I noticed that you are using const keyword and then trying to change its value. const means the value shouldn't change. Use either let or var in future if you want a variable to be mutable

Resources