I want to enable a button when two text fields have length > 0: How do I refer to these text fields lengths to express this? Seems simple, but its not obvious to me how to refer to the component's and their text (length). I basically want to use FRP to enable/disable button for form submission. These would be "sibling" components I suppose.
If two-way binding is an option, you could do something along these lines:
<input value='{{foo}}'>
<input value='{{bar}}'>
<button disabled='{{ !foo || !bar }}'>submit</button>
This works because the empty string ('') is falsy in JavaScript, so !foo || !bar is only false when both foo and bar are non-empty.
#Rich Harris: It seems that the problem with the <button disabled="{{ !(''+foo) || !(''+bar) }}">submit</button> trick is that the button is enabled at the start, because both foo and bar are initially undefined and ''+undefined gives the string 'undefined'. The technique also becomes unwieldy if you have several fields with various validation requirements.
As you may know, Angular has a $invalid that you can apply to a form, e.g., <button ng-disabled="myForm.$invalid">submit</button> where myForm is the form's name attribute. In Ractive, I guess one could write an isvalid function and then use <button disabled="{{ !isvalid() }}">submit</button> but that only works for one form (or is there some way to "attach" it to a particular element?).
Related
I'm trying to add custom validation logic to my react-bootstrap forms, but isInvalid doesn't seem to be respected. As soon as validated={true} is set on the form, it always validates non-empty strings, regardless of isValid or isInvalid. The invalid message is displayed, but the field shows as green. See here:
Here is the offending code:
<Form noValidate validated={formValidated} id="bidForm">
<Form.Group className="mb-3" controlId="formBasicBidding">
<Form.Label>Bid Amount</Form.Label>
<InputGroup hasValidation className="mb-3">
<InputGroup.Text id="inputGroupPrepend">$</InputGroup.Text>
<Form.Control
required
value={bidAmount}
isInvalid={!(parseInt(bidAmount) > 0) && formValidated}
onChange={e => setBidAmount(e.target.value)}
/>
<InputGroup.Text id="inputGroupAppend">.00</InputGroup.Text>
<Form.Control.Feedback type="invalid">
Please select a dollar amount {`>`} 0
</Form.Control.Feedback>
</InputGroup>
</Form.Group>
<...>
</Form>
I was able to get it to work using a pattern= regex on the input, but I'm planning to do more complex validation where a regex won't be sufficient. How can I get react-bootstrap to follow isValid and isInvalid properly? Thanks!
The docs don't do a great job of making this clear, but the form-level validated attribute hooks directly into HTML5's native validation library and can't be used simultaneously with other validation techniques. So if you're using the native option and an input doesn't violate any of the native validation options (required, pattern, etc), then the input will be considered valid. Since you don't have any of the native validation attributes besides required on your bid input, "foo" is valid as far as React-Bootstrap is concerned.
(If you're thinking 'well that's bad code design to let you use both simultaneously', I'd tend to agree with you.)
You'll note that with your current code, if you enter "foo" and submit the form the element actually does have an is-invalid class applied to it, but it's also got the :valid psuedo-selector applied to it because the entire form was validated, which seems to take precedence from a CSS perspective:
The best solution here is to use either the native HTML5 validation option (detailed here) or roll your own (with or without a helper library like Formik), but not both simultaneously.
If you're trying to avoid validating until the input is actually in a "dirty" state (e.g. the user filled it out or submitted the form), you can do something like this (CodePen here):
<Form.Control
required
value={bidAmount}
isInvalid={!(parseInt(bidAmount) > 0) && (bidAmount.length || formSubmitted)}
onChange={(e) => setBidAmount(e.target.value)}
/>
I have a form in reactstrap that has several input fields that uses FormFeedback like this:
<Input invalid={typeof data.name === "undefined" || data.name.length<1} bssize="sm" type="text" name="name" id="name" placeholder="Name" value={data.name} onChange={this.props.handleInputChange} />
<FormFeedback >A name is required</FormFeedback>
<Button color="primary" onClick={this.save} disabled={!this.state.okToSubmit}>Submit</Button>
Is it possible to have the submit button of the form disabled until all fields are validating ok?
I canĀ“t find any way to access the "invalid" prop of a field. The closest I have come so far is to look at the classList of target in the handleInputChange-function. But that feels very hacky and not the best way.
Quite new to React so all help is really appreciated.
There are a number of ways you can accomplish this: Since you are using onChange event handler, you can set another state var.
So, for example, say you have five form elements that you want to have be required. Every time an element is validated, increase that state var by one. Then add a conditional for the button to be disabled or not by disabled={this.state.okToSubmit != 5} (this can also be done using hooks if you're using a functional component.
Another option would be to keep the button live, and do all the validation within the onSubmit handler, but I think most modern day UX is to validate on a per element basis.
We have enabled autocomplete property true for all input fields. We didn't use form tags in the templates. The input fields don't fetch the previously entered data. So how can we implement autocomplete property.
Firstly, this is not specific to Aurelia. Once the element is in the DOM, it is a feature of the browser to offer the user a previously entered value for that field given that an assumption can be made about what the field is supposed to be!).
Depending on the browser, the autofill feature relies on having 'known' input attributes (name and type) and possibly even the surrounding text, including label text.
If you are not getting the expected results, try making sure your inputs have very obvious name attributes, first. Eg.
<input type="text" name="email">
If you could share a snippet of code, I might be able to offer more help.
I'm creating a CakePHP 3.0 form, and I have several input fields (Form->input) where users will enter values of United States Currency. I'd like to add a $ symbol to the left of the input box. From my research, it does not appear that CakePHP's Form supports this on its own, so I believe that a CSS solution would be ideal. The corresponding fields in the database are floats.
:before and :after are applied inside a container, which means you can use it for elements with an end tag.
Source
Basically, what that means is you cannot use before on inputs, since it would insert the content into the input.
You can do it with CSS's :before pseudo element, but you have to wrap the input in a element, or place an element before it:
.inputcon:before{
content:'$'
}
Or, you can do it with jQuery:
$("input").wrap("<span class='inputcon'>");
Or with Vanilla JS:
var inputs = document.getElementsByTagName("input");
for(var i =0;i<inputs.length;i++){
var wrapper = document.createElement("span");
wrapper.classList.add("inputcon")
inputs[i].parentNode.insertBefore(wrapper,inputs[i]);
wrapper.appendChild(inputs[i])
}
It sounds like you want to override the input template to include a $ before the input field. The default input template is <input type="{{type}}" name="{{name}}"{{attrs}}>, so it would change to $ <input type="{{type}}" name="{{name}}"{{attrs}}>.
http://book.cakephp.org/3.0/en/views/helpers/form.html#customizing-the-templates-formhelper-uses
You could override the entire form (probably not what you want), or just that one input. Most of the examples in the book show you how to override for the entire form, but you can override for just that one input field.
http://api.cakephp.org/3.0/class-Cake.View.Helper.FormHelper.html#_input
Restricting the field itself to only numbers/symbols that are appropriate for a currency is a javascript/html5 issue, separate from cake. If this is what you want, you should also validate server side with cake.
Additionally, somewhat off topic, currency fields should not be stored as floats in the database. They should be stored as some fixed precision type (such as the decimal type in mysql).
I have a checkbox list control on my asp.net web form that I am dynamically populating from an arraylist. In javascript I want to be able to iterate through the values in the list and if a particular value has been selected to display other controls on the page.
My issue is that all the values in the checkbox list are showing up as 'on' instead of the actual value set. How do I get the actual values for each checkbox?
Thanks.
Javascript:
checkBoxs=document.getElementById(CheckboxList);
var options=checkBoxs.getElementsByTagName('input');
for(var i=0;i<options.length;i++)
{
if(options[i].value=="Other")
{
if(options[i].checked)
{
var otherPub=document.getElementById('<%=alsOtherPublicity.ClientID%>');
otherPub.style.display='block';
}
}
}
Edit: The line that I'm having problems with is if(options[i].value=="Other") as the values showing up in firebug are given as 'on' rather than the values that I set.
Edit 2: The html that is produces looks like:
<span id="ctl00_ContentPlaceHolderMetadata_Allocation1_alfPublicity" class="ucFieldCBL" onChange="alValidate();" onClick="alPublicity('ctl00_ContentPlaceHolderMetadata_Allocation1_alfPublicity');">
<input id="ctl00_ContentPlaceHolderMetadata_Allocation1_alfPublicity_0" type="checkbox" name="ctl00$ContentPlaceHolderMetadata$Allocation1$alfPublicity$0"/>
<label for="ctl00_ContentPlaceHolderMetadata_Allocation1_alfPublicity_0">Text1</label>
<input id="ctl00_ContentPlaceHolderMetadata_Allocation1_alfPublicity_1" type="checkbox" name="ctl00$ContentPlaceHolderMetadata$Allocation1$alfPublicity$1"/>
<label for="ctl00_ContentPlaceHolderMetadata_Allocation1_alfPublicity_1">Text2</label>
<input id="ctl00_ContentPlaceHolderMetadata_Allocation1_alfPublicity_2" type="checkbox" name="ctl00$ContentPlaceHolderMetadata$Allocation1$alfPublicity$2"/>
<label for="ctl00_ContentPlaceHolderMetadata_Allocation1_alfPublicity_2">Text3</label>
<input id="ctl00_ContentPlaceHolderMetadata_Allocation1_alfPublicity_3" type="checkbox" name="ctl00$ContentPlaceHolderMetadata$Allocation1$alfPublicity$3"/>
<label for="ctl00_ContentPlaceHolderMetadata_Allocation1_alfPublicity_3">Text4</label>
<input id="ctl00_ContentPlaceHolderMetadata_Allocation1_alfPublicity_4" type="checkbox" name="ctl00$ContentPlaceHolderMetadata$Allocation1$alfPublicity$4"/>
<label for="ctl00_ContentPlaceHolderMetadata_Allocation1_alfPublicity_4">Text5</label>
</span>
It looks as if the issue stems from the lack of a value attribute available on the asp.net checkbox control as described by Dave Parslow. I'm currently trying a workaround by calling a function server side to return the text of the checkbox and using that instead.
options[i].checked will return true or false.
options[i].value will give you the value attribute of the checkbox tag.
I think your problem is not with the javascript but with the code that is populating the checkboxes. Are you binding the ArrayList as the CheckBoxList data source or iterating through the ArrayList and adding new ListItems to the CheckBoxList. If the former, consider switching to the latter and make sure that you use the ListItem constructor that takes both text and value parameters. If you look at the HTML source I suspect that you will see that the generated code has the value parameter set to on for all of your checkboxes which means that the values weren't actually bound in the codebehind.
Not 100% applicable here, but be aware that if you give a checkbox a cssclass, it gets a span wrapped around it, and the class is placed on that. This causes all sorts of cross browser problems when youre navigating the dom, or disabling checkboxes
I realised after much playing about with prerender events that I didn't actually need to know the exact value of the checkbox as the arraylist values would be in the same order as the checkboxes. I searched through the arraylist to get the position of the value that I needed and then used that position on the list of checkboxes.
It sounds a bit fiddly and I don't know if it would work for everyone but I thought I would put it up here anyway incase it helps someone else someday.
Thanks for all your help.