How to disable input filed using tailwind css and react conditionally? [duplicate] - javascript

This question already has answers here:
Conditional disabling of button
(2 answers)
Closed last month.
Hello Dev Community i am here with another issue can need your help.
i want to disable input field based on the Boolean state if the state is true then the input filed should be disable else it can be editable.
i have state variable isTrue which can be eithe true or false and here is the code
export function InputFiled(props) {
return (
<>
<input
className="py-2 pl-3 rounded-[14px] border-[1.3px] border-red-500"
placeholder={"Name"}
onChange={(e) => props.setData(e.target.value)}
value={props.data}
{...(!props.isTrue && "disabled")}
// here (below) it works fine but it is permanently disabled option
// disabled
/>
</>
);
}
The solution of this which i got form the attached (Conditional disabling of button) question is:
export function InputFiled(props) {
return (
<>
<input
className="py-2 pl-3 rounded-[14px] border-[1.3px] border-red-500"
placeholder={"Name"}
onChange={(e) => props.setData(e.target.value)}
value={props.data}
disabled={props.isTrue? true : false}
/>
</>
);
}

You may need to set additional tailwind css classes based on this state or prop which you want to baseline.
const [isDisabled, setDisabled] = useState(false);
//inside render
<input type='button'
onClick={(e)=> setDisabled(!isDisabled)}
disabled={isDisabled}
>

Related

Check if the form is updated in React JS

I have a form in my react application which is inside a modal pop up. so when the user closes the pop up i want to check if there is any changes made in the form fields.If so i will show a confirmation modal and if no changes i will close the pop up.
<FormProvider {...methods}>
<form onSubmit={handleSubmit(submitDetails)}>
<FormInput
onChange={handleChange(onChange, value)}
onBlur={onBlur}
value={value ?? ""}
name="name"
/>
<FormInput
onChange={handleChange(onChange, value)}
onBlur={onBlur}
value={value ?? ""}
name="age"
/>
<section className="submit-section">
<Button onClick={() => checkUnsavedAndClose()}>Cancel</Button>
<Button type="submit" disabled={!isValid}>
Save
</Button>
</section>
</form>
</FormProvider>
const checkUnsavedAndClose = () => {
// if the form is not updated
closePopUp();
// if the form is updated
alertPopup();
}
What is the best approach to validate the entire form irrespective of number of fields in it. i was thinking of checking whether the form is touched or dirty. but i am not sure that it would be the best solution. any inputs will be highly appreciated
Assuming the "handleChange" function is used for all inputs one thing you could do is use it to hold on state a variable for changes
handleChange(onChange, value) {
value !== originalValue && setState({anyChanges: true}) //or useState and set the state inside the modal
onChange(value)
}
you could also hold which fields were modified and not save to improve the pop-up message
by creating a boolean changed state. that you can change true/false. And you check the value when you try to close the popup.
const [changed, setChanged] = useState(false);
const handleChange() {
// your code
setChanged(true)
}
const checkUnsavedAndClose = () => {
if(changed) {
alertPopup();
} else {
closePopUp();
setChanged(false)
}

How to make a customed datepicker with selectable input? react

I have a simple problem in regards of changing input value. When I type a char the value was displayed, but my problem is the cursor stopped. This is the npm datepicker that I used by the way.
Can someone help me fix?
Play this demo video
Goal: is to create customed design input, that can change the date using datepicker and changing the directly to input.
Here is my code:
import DatePicker from 'react-datepicker';
const InputDate = () => {
const ExampleCustomInput = forwardRef(({ value, onClick }, ref) => (
<button>
<input
type='text'
onChange={(e) => setDate(e.target.value)}
value={date}
/>
</button>
));
return (
<div>
<DatePicker
selected={date}
customInput={<ExampleCustomInput />}
/>
</div>
);
};

Input validation - react form submitting without any values

I'm having an input validation problem thats allowing the form to submit without having any selectorValues added. The check I have seems to only check for input inside the textarea but doesn't account for the Add button being pressed.
Here's a sandbox reproducing the issue.
I'm using Semantic-ui-react so my <Form.Field /> looks like this:
<Form.Field required>
<label>Selector Values:</label>
<TextArea
type="text"
placeholder="Enter selector values 1-by-1 or as a comma seperated list."
value={this.state.selectorValue}
onChange={this.handleSelectorValueChange}
required={!this.state.selectorValues.length}
/>
<Button positive fluid onClick={this.addSelectorValue}>
Add
</Button>
<ul>
{this.state.selectorValues.map((value, index) => {
return (
<Card>
<Card.Content>
{value}
<Button
size="mini"
compact
floated="right"
basic
color="red"
onClick={this.removeSelectorValue.bind(this, index)}
>
X
</Button>
</Card.Content>
</Card>
);
})}
</ul>
</Form.Field>
So in the above, <TextArea> has a required prop: !this.state.selectorValues.length. This is only checking for input inside the textarea, it should check that the value has been added by pressing the Add button before allowing the form to submit.
In your addSelectorValue add a check to see if this.state.selectorValue it not empty, if it is just return, this will prevent adding empty values to selectorValues
addSelectorValue = e => {
e.stopPropagation();
e.preventDefault();
if (!this.state.selectorValue) return;
//continue if this.state.selectorValue has a value
};
Before submitting add a check to see if this.selectorValues is empty, if so focus on textarea.
To focus we need to first create a ref to our textarea.
Create a ref to be
attached to a dom element
textareaRef = React.createRef();
// will use our ref to focus the element
focusTextarea = () => {
this.textareaRef.current.focus();
}
handleSubmit = () => {
const { selectorValues } = this.state;
if (!selectorValues.length) {
// call our focusTextarea function when selectorValues is empty
this.focusTextarea();
return;
}
this.setState({ submittedSelectorValues: selectorValues });
};
// attach our ref to Textarea
<Textarea ref={this.textareaRef} />
After some search ... required prop is for decorational purposes only - adding astrisk to field label.
It has nothing to form validation. You need a separate solution for that - try formik or set some condition within submit handler.
Formik plays nicely with yup validation schema - suitable for more complex, dynamic requirements.

Redux Form: Conditional form validations with multiple submit buttons

I am using Redux forms with multiple submit buttons along with redux-form <Field />. I need to control the validation of these fields based on click of these buttons. For ex. I need to set a flag to True/False based on click of these buttons so that I can conditionally validate my fields like below:
<Field
name="date"
component={DateFormField}
validate={isSaveDraft && [validateRequiredText]}
floatingLabelText="Date"
fullWidth
helpText="blablabla"
/>
<Field
name="title"
component={TextFormField}
normalizeOnBlur={normalizeTextOnBlur}
validate={!isSaveDraft && [validateRequiredText]}
floatingLabelText="Project title"
fullWidth
helpText="blablabla"
/>
As you can see from above code, I'm conditionally validating my fields with validate={isSaveDraft && [validateRequiredText]} and validate={!isSaveDraft && [validateRequiredText]}
Here are my two submit buttons:
<RaisedButton
label={submitting ? 'Saving Draft...' : 'Save Draft'}
type="button"
onClick={handleSubmit(values => onSubmit())}
disabled={submitting}
primary
/>
<RaisedButton
label={submitting ? 'Submitting Brief...' : 'Submit Brief'}
type="button"
onClick={handleSubmit(values => onSubmit())}
disabled={submitting}
primary
/>
However, I'm not able to achieve it. Please help.
After a lot of headaches and head scratching, I've finally found the solution without making things look ugly. Thanks to a fellow developer for this solution. Original idea was to set a flag on click of the button and conditionally validate the fields. (PS: I'm using Field Level Validations). However, the issue was that the validations are being executed BEFORE the flag setting as the onClick handler wouldn't fire before all the validations are fixed and that logic is buried deep inside redux-forms (perks of unnecessarily overcomplicating simple things by using a library).
Here is the solution:
submit handler
handleSubmit() {
const { bookingCreate, modalShow, navigateTo } = this.props;
const { isDraftAction } = this.state; // my flag
// create record!
return bookingCreate(isDraftAction)
.then(responsePayload => {
...
})
.catch(handleSubmissionError);
}
isDraftAction is the flag which is set (in local state) when the action is called on onClick of both buttons.
My conditional Field level validations
<Field
name="date"
component={DateFormField}
validate={isDraftAction && [validateRequiredText]}
fullWidth
helpText="blablabla"
/>
<Field
name="title"
component={TextFormField}
normalizeOnBlur={normalizeTextOnBlur}
validate={!isDraftAction && [validateRequiredText]}
fullWidth
helpText="blablabla"
/>
My 2 buttons for SAVE RECORD and SUBMIT RECORD.
const submit = handleSubmit(values => onSubmit()); // this is redux-form's submit handler which will in-turn call my own submit handler defined above. (That's where the library hides all the logic and makes developer helpless)
<RaisedButton
label={submitting && isDraft ? 'Saving Draft...' : 'Save Draft'}
type="button"
onClick={() => {
this.props.dispatchAction({ draftAction: true }).then(() => {
submit();
});
}}
disabled={submitting}
primary
/>
<RaisedButton
label={submitting && !isDraft ? 'Submitting Brief...' : 'Submit Brief'}
type="button"
onClick={() => {
this.props.dispatchAction({ draftAction: false }).then(() => {
submit();
});
}}
disabled={submitting}
primary
/>
dispatchAction() is my action function which will FIRST set the flag to true/false THEN call redux-forms inbuilt submit handler. Also, I've extracted the redux-form's submit handler as it is above only for more clarity.
dispatchAction()
dispatchAction={({ draftAction }) =>
new Promise(resolve => {
this.setState({ isDraftAction: draftAction }, resolve);
})
}
use a state variable as isSaveDraft and set it default to false
Add onClick action of button to set state.isSaveDraft = true
validate={(isSaveDraft && [validateRequiredText]} will not work since validate expects a function all the time. Also, field level validation happens onTouch, or onBlur etc. which is way too early as you won't know which button will be clicked.
What you need to do is use a extra flag prop to hold which button was clicked and then use that in the form level validation.
So your Fields will look like this (no more Field level validation):
<Field
name="date"
component={DateFormField}
floatingLabelText="Date"
fullWidth
helpText="blablabla"
/>
...
<RaisedButton
label={submitting ? 'Saving Draft...' : 'Save Draft'}
onMouseDown={() => this.setDraftFlag(true)}
...
/>
<RaisedButton
label={submitting ? 'Submitting Brief...' : 'Submit Brief'}
onMouseDown={() => this.setDraftFlag(false)}
...
/>
I'm using onMouseDown to capture the flag since you're already using onClick for submitting the form. Besides, we need to do the validation before submit anyway.
And then in your form's validate (based on SyncValidation example)
const validate = values => {
const errors = {}
const {isDraft, ...rest} = values
if(isDraft) {
// draft validations
} else {
// other validations
}
return errors
}
export default reduxForm({
form: 'myForm', // a unique identifier for this form
validate, // <--- validation function given to redux-form
})(MyForm)
setDraftFlag can be an action or you can make it part of your Form component like so (I find this easier since you already get change bound to your form):
setDraftFlag(value) {
this.props.change('isDraft', value));
}

Stripe Card Element default postcode

I'm integrating Stripe Elements in my React project, using this simple component:
render () {
return (
<form onSubmit={event => this.onSubmit(event)}>
<label>
<CardElement className='Input' />
</label>
</form>
)
}
Problem is that I already have another form above where the user enters its billing info (address, zip code, country...). is it possible to pre-fill this field with the Zip code already entered before?
I've looked into Elements source code and see no value option possible. Is it possible somehow to use ref option to do so?
Thanks
According to this: https://stripe.com/docs/stripe-js/reference#elements-create (in options), you can pass the option value, I see here: https://github.com/stripe/react-stripe-elements/blob/master/src/components/Element.js#L26 that any viable option is allowed:
render () {
return (
<form onSubmit={event => this.onSubmit(event)}>
<label>
<CardElement
className='Input'
value={ { postalCode: this.state.postcode } }
/>
</label>
</form>
)
}

Categories