My web application uses forms laid out as in the example below...
First Name [____________]
Last Name [____________]
Gender () Male () Female
The markup I use is something like...
<label for="firstName">First Name</label><input type="text" id="firstName" />
<label for="lastName">Last Name</label><input type="text" id="lastName" />
<label>Gender</label>
<fieldset>
<legend>Gender</legend>
<input type="radio" name="sex" id="sex-m" value="m">
<label for="sex-m">Male</label>
<input type="radio" name="sex" id="sex-f" value="f">
<label for="sex-f">Female</label>
</fieldset>
I have the following issues that I don't know how to solve...
I want to have the WHOLE GROUP of radio buttons labelled like any other field (as in the diagram above), but there is nothing to link the label to (i.e. nothing for its "for" attribute, since each radio in the group has its own label just for the value of the individual radio button) A label without a "for" attribute will not pass accessibility compliance.
The <legend> element of the fieldset seems to duplicate the function of the label. Is this really necessary?
I had thought about styling the <legend> tag to appear as though it's a label, and dispense with the label altogether for the radio button group, but that seems a bit hacky to me, and will also introduce complexities elsewhere in my code (which relies on <label> elements to do some nifty validation message markup and various other things)
Thanks in advance.
The first part of Ssollinger's answer is correct:
The code should be:
<label for="firstName">First Name</label><input type="text" id="firstName" />
<label for="lastName">Last Name</label><input type="text" id="lastName" />
<fieldset>
<legend>Gender</legend>
<input type="radio" name="sex" id="sex-m" value="m">
<label for="sex-m">Male</label>
<input type="radio" name="sex" id="sex-f" value="f">
<label for="sex-f">Female</label>
</fieldset>
When assistive technology hits the male radio button, most will read as: "Gender: male radio button 1 of 2 not selected."
Then you could use CSS on the fieldset, legend, the labels and inputs. If memory serves correctly fieldsets can be a bear to style, so i might end up adding a <div> to it:
<label for="firstName">First Name</label><input type="text" id="firstName" />
<label for="lastName">Last Name</label><input type="text" id="lastName" />
<fieldset>
<legend>Gender</legend>
<div>
<input type="radio" name="sex" id="sex-m" value="m">
<label for="sex-m">Male</label>
<input type="radio" name="sex" id="sex-f" value="f">
<label for="sex-f">Female</label>
</div>
</fieldset>
Adding this <div> has no accessibility implications.
Like in the comment in ssollinger's answer, you could dump the fieldset and legend approach, but you would need to build everything to make it accessible, an example of a build out
I had thought about styling the <legend> tag to appear as though it's a label, and dispense with the label altogether for the radio button group, …
This is the correct way to do it. "Gender" is not a label for anything, the labels for the radio boxes are "male" and "female". "Gender" is the legend of the fieldset which groups the radio buttons together. The correct way to implement this form is to remove the "Gender" label and just leave the fieldset with legend "Gender".
Technically, you could probably add a <div> around the radio buttons and point the for= of the "Gender" label to that, but I'm quite sure that this will cause accessibility problems (haven't tried it with a screen reader though) so I would strongly recommend to get rid of the label for "Gender".
Related
I have a react sign-up form. I want to set up an input (checkbox) that holds the value as some text - e.g:
<form onSubmit={this.validateStepTwo} id="registerForm">
<label htmlFor="short_bio">Tell the users a bit about yourself:</label>
<input type="textarea" name="short_bio" className="textarea-small"/>
<label htmlFor="bio_info">Tell the users who you are</label>
<input type="textarea" name="bio_info" className="textarea-large"/>
<label htmlFor="bio_exp">Tell the users what you did</label>
<input type="textarea" name="bio_exp" className="textarea-large"/>
<input type="checkbox" name="instructor" value="I want to be an instructor" />
<input type="submit" value="Register" className="submit"></input>
{this.state.errors !== null ? (
<h1 className="error">{this.state.errors}</h1>
) : ('')}
</form>
Where
<input type="checkbox" name="instructor" value="I want to be an instructor" />
should have a value of "I want to be an instructor" but it doesnt have anything.
I tried doing it like this:
<input ...>I want to be an instructor</input>
but that threw another error.
Is this a react thing or am i missing something in my code? Ive been on the computer for 13 hours so i wouldnt be surprised if i made a dumb mistake.
Checkbox input value is the one sent in the request and not the text that appears afterwards.
If you want it to be the text then do something like this
<input type="checkbox" name="instructor" value="instructor"> I want to be an instructor
I tried many answers here at Stackoverflow, but none of them working:
<form ng-submit="runIt(cars)">
<input type="radio" ng-model="cars.erp" value="Toyota" ng-required="!cars.erp">Toyota
<br>
<input type="radio" ng-model="cars.erp" value="Nissan" ng-required="!cars.erp">Nissan
<br>
<input type="radio" ng-model="cars.erp" value="Honda" ng-required="!cars.erp">Honda
<br>
<input type="radio" ng-model="cars.erp" value="Other" ng-required="!cars.erp">Other
<input type="text" ng-model="cars.other" ng-show="cars.erp=='Other'" ng-required="!cars.other">
<br>
<input type="submit">
</form>
It all starts working only after typing a value in Other. Apparently, this is due to hidden input, but this is how it should work:
A value must be submitted,
If Other selected, value must be typed.
Here's the fiddle: http://jsfiddle.net/ADukg/17426/
To reproduce:
Run
Select Toyota
Click Submit
See Console in Inspect
The reason for the specific error you're getting of "invalid form control with name='' is not focusable" is because the browser wants to focus on the form element that is required(the text input), but the element is not visible.
<input type="text" ng-model="cars.other" ng-show="cars.erp=='Other'" ng-required="!cars.other">
You're saying that the text field is only required if cars.other evaluates to false. In other words, you're saying that the text field is required whenever it isn't filled out. What you actually want is for the text field to be required if cars.erp is set to other.
<input type="text" ng-model="cars.other" ng-show="cars.erp=='Other'" ng-required="cars.erp=='Other'">
Your text field's ng-model is cars.other and then you are checking for ng-required="!cars.other" which isn't right. You are requiring the text field with it self. Instead it should be dependent on the value of the radio button. Something like ng-required="cars.erp=='Other'".
I have updated the JSFiddle here -> http://jsfiddle.net/d0o29hb2/3/. Hope this helps.
I have tried using HTML-DOM...but the problem is that they don't seem to be working with radio buttons.
Is there somthing which would help me in this using purely angular?
I have tried many methods but the problem with radio button continues.
please help me find a solution soon..
Toy material:
<input type="radio" name="Ttyp" ng-model="1" value="plastic" required>plastic
<input type="radio" name="Ttyp" ng-model="2" value="wood" required>wood<br><br>
<div ng-show="2">
toy name: <input type="radio" name="Tname" ng-required="2" value="Our Venue">Our Venue
<input type="radio" name="Tname" ng-required="2" value="Your Venue">Your Venue
</div>
<br><br>
edit
https://docs.angularjs.org/api/ng/directive/ngSwitch {may be this could help}
I created this simple example: http://jsfiddle.net/5Bh59/.
If you switch between AngularJS 1.2.1 and 1.1.1, you'll see the radio buttons don't work properly in either version. If you watch the radio button's $dirty field, 1) for version 1.1.1, it will only be set when the first button is clicked, and 2) for version 1.2.1, it will only be set when the last button is clicked.
I read this answer: AngularJS Radio group not setting $dirty on field but I don't really understand the answer. Not only that but the fiddler example demonstrates the same behavior.
So, is this a bug in AngularJS and how can I work around it?
You either need to give each radio button input a different name, or you need to wrap each radio button in an ng-form (each of which have a different name). If you use two inputs with the same name in the same form, only the last one will be bound to the property on the FormController. If you use different names, then each input will have its own property on the FormController.
Example with different names for each radio button:
http://jsfiddle.net/BEU3V/
<form name="form" novalidate>
<input type="radio"
name="myRadio1"
ng-model="myRadio"
ng-click=""
value="Rejected"
required>Rejected<br />
<input type="radio"
name="myRadio2"
ng-model="myRadio"
ng-click=""
value="Approved"
required>Approved<br />
Form $dirty: {{form.$dirty}}<br />
Field1 $dirty: {{form.myRadio1.$dirty}}<br />
Field1 $dirty: {{form.myRadio2.$dirty}}<br />
Value: {{myRadio}}
</form>
Example wrapping with ng-form:
http://jsfiddle.net/39Rrm/1/
<form name="form" novalidate>
<ng-form name="form1">
<input type="radio"
name="myRadio"
ng-model="myRadio"
ng-click=""
value="Rejected"
required>Rejected<br />
</ng-form>
<ng-form name="form2">
<input type="radio"
name="myRadio"
ng-model="myRadio"
ng-click=""
value="Approved"
required>Approved<br />
</ng-form>
Form $dirty: {{form.$dirty}}<br />
Field1 $dirty: {{form.form1.myRadio.$dirty}}<br />
Field2 $dirty: {{form.form2.myRadio.$dirty}}<br />
Value: {{myRadio}}
</form>
If you'd like a single check for the radio group, you can wrap all the radio buttons in their own ng-form and call it something like name="radioGroup".
http://jsfiddle.net/6VVBL/
<form name="form" novalidate>
<ng-form name="radioGroup">
<input type="radio"
name="myRadio1"
ng-model="myRadio"
ng-click=""
value="Rejected"
required>Rejected<br />
<input type="radio"
name="myRadio2"
ng-model="myRadio"
ng-click=""
value="Approved"
required>Approved<br />
</ng-form>
Form $dirty: {{form.$dirty}}<br />
Group $valid: {{form.radioGroup.$valid}}<br />
Group $dirty: {{form.radioGroup.$dirty}}<br />
Value: {{myRadio}}
</form>
This answer is related but perhaps not exactly applicable, but after finding and reading this item I felt it valuable to provide, and I don't have enough points to just comment on an answer (which I thought would have been a more appropriate way to respond).
My issue was that I wanted to show a required error (using ng-messages) but when you tabbed through / past the radio button group $touched didn't turn true unless you shift-tabbed back from the next UI element back to the last radio button of the group. (When my form renders the radio buttons are not set - I'm wanting the user to make a selection and not rely on the user accepting a default.)
Here's my code:
<div class="form-group" ng-class="{'has-error': pet.genderId.$invalid && pet.genderId.$touched}">
<label class="control-label">
What is your pet's gender?
<span ng-messages="pet.genderId.$error" ng-show="pet.genderId.$invalid && pet.genderId.$touched">
<span ng-message="required">(required)</span>
</span>
</label>
<div>
<label class="radio-inline"><input type="radio" ng-model="genderId" name="genderId" value="1" required ng-blur="pet.genderId.$setTouched();" />Male</label>
<label class="radio-inline"><input type="radio" ng-model="genderId" name="genderId" value="2" required ng-blur="pet.genderId.$setTouched();" />Female</label>
<label class="radio-inline"><input type="radio" ng-model="genderId" name="genderId" value="3" required ng-blur="pet.genderId.$setTouched();" />Not sure</label>
</div>
</div>
The 'magic' was adding the ng-blur attribute to set 'touched' myself even if only the first radio button was tabbed past.
You may be able to employ a similar tactic for $dirty by calling $setDirty() in the ng-changed attribute.
In AngularJS, I'm trying to add/remove a checked class on a parent element, when its child radio button is checked/unchecked.
<label ng-class="{checked: menuType.isChecked0}">
<input type="radio" name="menuType" ng-model="menuType.isChecked0" />Text 1
</label>
<label ng-class="{checked: menuType.isChecked1}">
<input type="radio" name="menuType" ng-model="menuType.isChecked1" />Text 2
</label>
Here is a fiddle: http://jsfiddle.net/fAA2w/
There is no controller or any other relative code. If there is a better way to approach this, please share. This seems simple enough, but I cannot find an answer to this question. What am I doing wrong here?
You need to give the radio input a value.
For more examples see http://docs.angularjs.org/api/ng/input/input%5Bradio%5D.
<div ng-app>
<label ng-class="{checked: isChecked == 1}">
<input type="radio" name="menuType" ng-model="isChecked" value="1" />Text 1
</label>
<label ng-class="{checked: isChecked == 2}">
<input type="radio" name="menuType" ng-model="isChecked" value= "2" />Text
</label>
</div>
This is the correct way to be doing it. Reason being, when your ng-model changes, your ng-class will pick up on that and update the view, the Angular way!