If statement within an input field - reactjs

I am using Bootstrap with React and there is an option within an input <input ... readonly/> field to set readonly, now I have an input field set to readonly. However, when the user clicks on a button, I want the readonly mode to disappear and the user to be able to use that input field. However, my if statement does not work. What is the best way to do this?
What I tried
{ clicked ?
readOnly : null
}
My Code
const Profile = () => {
const [clicked, setClicked] = useState(true);
const onClickBack = () => {
setClicked(false);
}
return (
<div>
<div className="form-group">
<div className="col-xs-4">
<label for="exampleInputName">Name</label>
<input
type="text"
className="form-control"
placeholder="Name"
// THIS IS WRONG ā†“
{ clicked ?
readOnly : null
}
// THIS IS WRONG ā†‘
/>
</div>
</div>
<button
type="button"
id="submit"
name="submit"
className="btn btn-primary submit-button ml-5"
onClick={onClickBack}
>
Back
</button>
</div>
);
};
export default Profile;

This should work...
<input readOnly={!clicked}/>

Related

empty data instead of data from the array when changing the data in the input react js

I have a simple todo list that consists of multiple inputs.
I made the editing functionality and now everything works as it should, but only once. When I change the input data for the first time, it saves everything to an array with the correct data.
And when I want to do it a second time, then in order to save this data, three inputs must be changed.
I want that even when changing one input, the data is saved in an array (data that has not been changed is overwritten).
Stackblitz code
App.js
function App(props) {
const [tasks, setTasks] = useState(props.tasks);
function editTask(id, newName, newTranslate, newNote) {
const editedTaskList = tasks.map((task) => {
if (id === task.id) {
return { ...task, name: newName , translate: newTranslate , note: newNote };
}
return task;
});
setTasks(editedTaskList);
}
const taskList = tasks
.map((task) => (
<Todo
id={task.id}
name={task.name}
translate={task.translate}
note={task.note}
completed={task.completed}
key={task.id}
editTask={editTask}
tasks={tasks}
/>
));
return (
<div className="todoapp stack-large">
<ul
className="todo-list stack-large stack-exception"
aria-labelledby="list-heading">
{taskList}
</ul>
</div>
);
}
export default App;
I did a check and added the save button onClick which outputs the data to the console. It gives the data correctly the first time, and if the same item in the todo is changed the second time, it gives an empty space instead of the data that has not been changed.
Todo.js
export default function Todo({name, translate, note, editTask, id, tasks}) {
const [isEditing, setEditing] = useState(false);
const [newName, setNewName] = useState(name);
const [newTranslate, setNewTranslate] = useState(translate);
const [newNote, setNewNote] = useState(note);
function handleChange(e) {
setNewName(e.target.value)
}
function handleChangeTranslate(e) {
setNewTranslate(e.target.value);
}
function handleChangeNote(e) {
setNewNote(e.target.value)
}
function handleSubmit(e) {
e.preventDefault();
if (!newName.trim()|| !newTranslate.trim() || !newNote.trim()) {
return;
}
editTask(id, newName,newTranslate,newNote);
setNewName("");
setNewTranslate("");
setNewNote("");
setEditing(false);
}
const editingTemplate = (
<form className="stack-small" onSubmit={handleSubmit}>
<div className="form-group">
<input
id={id}
className="todo-text"
type="text"
autoComplete='off'
defaultValue={newName || name}
onChange={handleChange}
placeholder="write word"
/>
<input
id={id}
className="todo-text"
type="text"
autoComplete='off'
defaultValue={newTranslate || translate}
onChange={handleChangeTranslate}
placeholder="write translate"
/>
<input
id={id}
className="todo-text"
type="text"
autoComplete='off'
defaultValue={newNote || note}
onChange={handleChangeNote}
placeholder="write note"
/>
</div>
<div className="btn-group">
<button
type="button"
className="btn todo-cancel"
onClick={() => setEditing(false)}
>
Cancel
</button>
<button type="submit" className="btn btn__primary todo-edit" onClick={()=>console.log(newName, newTranslate, newNote)}>
Save
</button>
</div>
</form>
);
const viewTemplate = (
<div className="stack-small">
<div className="c-cb">
<label className="todo-label" htmlFor={id}>
{name}
</label>
<label className="todo-label" htmlFor={id}>
{translate}
</label>
<label className="todo-label" htmlFor={id}>
{note}
</label>
</div>
<div className="btn-group">
<button
type="button"
className="btn"
onClick={() => setEditing(true)}
>
Edit <span className="visually-hidden">{name}</span>
</button>
</div>
</div>
);
return <li className="todo">{isEditing ? editingTemplate : viewTemplate}</li>;
}
Since you want to keep those preview state which was not edit and still print out those state with the one you edit, you can just remove all the "reset state '' you put, since all your initial state from useState already had a value and is not an empty string "" like this
function handleSubmit(e) {
e.preventDefault();
if (!newName.trim()|| !newTranslate.trim() || !newNote.trim()) {
return;
}
editTask(id, newName,newTranslate,newNote);
setEditing(false);
}

React showing value required on edit case even if the field is already populated

I am using react-hook-form and Joi for the validataion in react. But in case of edit, if I don't touch any field and hit directly update, it shows value required, even when the field is already populated there.
But, once I focus or clicked on the input field, and hit update, then its get updated.
Here is the form:
const MarketplaceForm = ({ submitAction, submitBtnText, item }) => {
//joi schema
const schema = Joi.object({
name: Joi.string().required().min(3).max(191).label("Marketplace Name"),
});
//react hook form setup
const {
register,
handleSubmit,
setError,
clearErrors,
formState: { errors },
} = useForm({
resolver: joiResolver(schema),
});
const onSubmit = async (input) => {
submitAction(input, setError);
};
return (
<div className="intro-y box p-5">
<form id="add_marketplace_form" onSubmit={handleSubmit(onSubmit)}>
<div>
<label htmlFor="crud-form-1" className="form-label">
Marketplace Name
</label>
<input
className={`form-control w-full ${
errors["name"] ? "border-red-500" : ""
}`}
type="text"
id="name"
name="name"
autoComplete="on"
{...register("name")}
defaultValue={item.name ?? ""}
/>
<ErrorSpan errors={errors} fieldName="name" />
</div>
<div className="text-right mt-5">
<button
type="button"
className="btn btn-outline-secondary w-24 mr-1"
>
Cancel
</button>
<button type="submit" className="btn btn-success w-24">
{submitBtnText}
</button>
</div>
</form>
</div>
);
};
export default MarketplaceForm;
I guess you should check validation as your validation is not working properly or see the name props
is this default value working
defaultValue={item.name ?? ""}

Unable to type in input field React

I am creating a simple todo list. In here there is a modal for the update form,I can take the relevant values from the state And set them to the input field values. then I can't edit the input fields. I think the problem is with the onChange function or value property
import React from 'react'
import {useRef,useState,useEffect} from 'react'
import {FaTimes} from 'react-icons/fa'
export const Modal = ({edData,showModal,setShowModal,onAdd,setEd,tasks}) => {
const [text,setText] = useState('')
const[day,setDay] = useState('')
const[reminder,setReminder] = useState(false)
useEffect(() => {
if(edData!=null){
for(let i=0;i<tasks.length;i++)
{
if(tasks[i].id===edData){
// console.log(tasks[i])
setText(tasks[i].text)
setDay(tasks[i].day)
setReminder(tasks[i].reminder)
}
}
}
// inputText.current.value = edData.text;
// inputDay.current.value = edData.day;
// inputReminder.current.value = edData.reminder;
});
const closeModal = () =>{
setEd(null)
setShowModal(prev=>!prev)
setText('')
setDay('')
setReminder(false)
}
const onSubmit = (e) =>{
e.preventDefault()
if (!text){
alert('Please add a task')
return
}
onAdd({text,day,reminder})
setText('')
setDay('')
setReminder(false)
setShowModal(prev=>!prev)
}
return (
<>
{showModal?
<div className="background">
<div className="ModalWrapper" >
<div className="ModalContent">
<h2 className="modalTitle">{edData==null? 'Add New Task':'Update Task'}</h2>
<form className="add-form" onSubmit={onSubmit}>
<div className="form-control">
<label htmlFor="">Task</label>
<input type="text" placeholder="Add Task" name="" id="" value={text} onChange={(e) => setText(e.target.value)}/>
</div>
<div className="form-control ">
<label htmlFor="">Date & Time</label>
<input type="text" placeholder="Add Date and Time" name="" id="" value={day} onChange={(e) => setDay(e.target.value)}/>
</div>
<div className="form-control form-control-check">
<label htmlFor="">Set Reminder</label>
<input type="checkbox" checked={reminder} name="" id="" value={reminder} onChange={(e) => setReminder(e.currentTarget.checked)}/>
</div>
<input className="btn btn-block" type="submit" value="Save Task" />
</form >
</div>
<div className="CloseModalButton" onClick={closeModal}>
<FaTimes/>
</div>
</div>
</div>
: null}
</>
)
}
If you don't pass a dependency array to useEffect it will be called on every render, calling setText inside of it and overwriting the input's value, pass an empty array to useEffect if you don't want it to run on every render :
useEffect(() => {
// ....
}, []);

Trying to disable Send button when there are errors

I have this form in a react-redux component.
The problem is that Iā€™m trying to make the Send button disabled when the input.trim() is empty.
It is not behaving as expected.
If I type something, the button remains disabled,
export default function TodoInput() {
const [todoText, setTodoText] = React.useState('');
const [errors, setErrors] = React.useState('');
const dispatch = useDispatch()
function validate(text) {
text.trim()
return (text.length !== 0 ? 'Error' : '')
}
function handleInputChange(e) {
setTodoText((e.target.value).trim())
setErrors(validate(e.target.value));
}
function submitButton() {
if (errors.length !== 0)
return <input type="submit" onSubmit={onSubmit} className="btn btn-primary mx-2" disabled/>
else
return <input type="submit" className="btn btn-primary mx-2"/>
}
function onSubmit() {
dispatch(todoAdded(todoText))
}
return (
<div>
<div className="row m-2">
<form className={style.todoForm}
onSubmit={(e) => {
e.preventDefault(); // the default behavior is to refresh the whole window
onSubmit(todoText);
setTodoText('')
}}>
<input type="text"
className="col form-control"
placeholder="Todo Text..."
name="todoText"
value={todoText}
onChange={handleInputChange}
/>
{submitButton()}
</form>
</div>
</div>
)
}
What could it be?
Thanks in advance
Rafael

ReactJS add multiple input fields dynamically

Hello I am new to React and am lost at trying to figure out how to add input field dynamically with React.
If someone can please help me in figuring out how to bind an onclick to add another field dynamically to the form.
How can i click add button and another option input will render
class AddPost extends Component {
static contextTypes = {
router: React.PropTypes.object
};
appendInput() {
var newInput = `input-${this.state.inputs.length}`;
this.setState({ inputs: this.state.inputs.concat([newInput]) });
}
handleFormSubmit(formProps){
this.props.addPost(formProps);
this.context.router.push('/posts');
}
render(){
const {handleSubmit,fields:{title,option}} = this.props;
return (
<div className="row top-buffer">
<div className="col md-auto">
<form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
<fieldset className="form-group">
<label>Question:</label>
<input {...title} className="form-control" placeholder="Enter question here"/>
{title.touched && title.error && <div className="text-danger">{title.error}</div>}
</fieldset>
<fieldset className="form-group">
<label>Option:</label>
<input {...option} className="form-control" placeholder="Enter option"/>
{option.touched && option.error && <div className="text-danger">{option.error}</div>}
</fieldset>
<fieldset className="form-group">
<label>Option:</label>
<input {...option} className="form-control" placeholder="Enter option"/>
{option.touched && option.error && <div className="text-danger">{option.error}</div>}
</fieldset>
<button className="btn btn-success">Add</button>
</form>
<button onClick={ () => this.appendInput() }>
CLICK ME TO ADD AN INPUT
</button>
</div>
</div>
);
}
}
function validate(formProps){
const errors = {};
if(! formProps.title){
errors.title = "Title is required";
}
if(! formProps.option){
errors.body = "Option is required";
}
return errors;
}
function mapStateToProps(state){
return {
posts:state.post
}
}
export default reduxForm({
form:'post',
fields:['title','body'],
validate:validate,
},mapStateToProps,{addPost})(AddPost);
If you are using redux-form. Checkout the example with FieldArray, that should help.

Resources