How can I make screen reader not to read aria labels of elements inside of a group - accessibility

I have a page structured as following.
<div>
<div>
<h2>header</h2>
<button>close button</button>
</div>
<div>
<div>some info</div>
<div roll='groub' aria-label='some general text about which checkbox is selected'>
<div>
<input type="checkbox" id="scales" name="scales" checked aria-label="scales">
<label for="scales">Scales</label>
</div>
<div>
<input type="checkbox" id="horns" name="horns" aria-label="horns">
<label for="horns">Horns</label>
</div>
</div>
</div>
</div>
I have my screen reader on and want to be able to tab from each ui component, and screen reader reads it out for me as I press tab key.
when it reaches to the div with roll of group, then it reads out the aria label of that div element plus all of its children!
What I want is to read only the aria-label of the div with roll of group and stops. Then only reads the aria label of the checkboxes when I tab into them.
any suggestion on what roll I should define for input elements so they get announced only when they are focused by tab key ?

The question should be how to use groups to build a screen reader friendly form.
When it comes to checkboxes or radio buttons, a group is the correct way to go, as it will bind the overall question to the controls, which are in tab order.
So that would be something like
Close button, button
Tab
some general text about which checkbox is selected, group
Scales, checkbox, unchecked
The group itself will not be focussed. But when focussing the first checkbox, the screen reader will announce the group’s name once. This will help screen reader users choose the right one. Once they change to the next checkbox, the group’s name will not get announced.
This is how it should work, since forms are used mainly by means of Tab and the user needs to get the info about what the checkboxes are about.
To follow the First Rule of Using Aria, you should use a <fieldset> element with a <legend>.
If you can use a native HTML element [HTML51] or attribute with the semantics and behavior you require already built in, […] then do so.
You should not provide aria-label attributes when there is a visual label already. It is correctly used with a for attribute, hence is already providing an accessible name to the checkbox.
<div>
<div>
<h2>header</h2>
<button>close button</button>
</div>
<div>
<div>some info</div>
<fieldset>
<legend>some general text about which checkbox is selected</legend>
<div>
<input type="checkbox" id="scales" name="scales">
<label for="scales">Scales</label>
</div>
<div>
<input type="checkbox" id="horns" name="horns">
<label for="horns">Horns</label>
</div>
</fieldset>
</div>
</div>

Related

Adding HTML in Text Area. Text Area not showing value when inspect element

I write a text in text area box but what I write is not showing via inspect element. Please help I want it show what I write in text box when I inspect element it.
<div class="F0XO1GC-j-k">
<label for="gwt-uid-4809"> Write an invitation message </label>
<textarea class="gwt-TextArea F0XO1GC-Nb-g" rows="10" id="gwt-uid-4809" dir="ltr"></textarea>
<div class="F0XO1GC-Nb-o" aria-hidden="true" style="display: none;"></div>
<div class="F0XO1GC-b-S F0XO1GC-Nb-f" style="display: none;" aria-hidden="true"></div>
<div class="F0XO1GC-b-Db"> The group's name, description, and address will automatically be included in the email. </div>
</div>
I expect it to show value when I inspect element it.
Your expectations are wrong. This is normal behaviour.
The content of the textarea element is the default value of the field (used to initially populate the field and set its value when a reset button is activated).
The value you type into it is the current value.
The DOM inspector shows you the content, so it shows the default value.
When you submit the form, or read its value property with JavaScript, you will get the current value.

Having an Angular Dynamic Form Generator Bootstrap CSS Issue

I am attempting a dynamic form generator based on Angular's Dynamic Forms template using Angular 7 and I'm running into a css issue. I am using Bootstrap 4.0 and I hope it's not an issue where I need to go back to 3.0 (I had a prior issue that involved that, but correct re-coding got it to work in 4.0). If so, please let me know.
Now, here is the way that my app works correctly for my end product. My code to generate the drop downs is:
<div class="row">
<div *ngFor="let question of questions" class="col-md-6 form-group">
<label for="{{question.key}}">{{question.label}}</label>
<span [ngSwitch]="question.controlType">
<select *ngSwitchCase="'dropdown'"
[id]="question.key"
[formControlName]="question.key"
[className]="question.fieldClass">
<option *ngFor="let opt of question.options" [ngValue]="opt.value">{{opt.name}}</option>
</select>
</span>
<span class="help-block error" *ngIf="isFormTouchedAndInvalid(question.key)">{{question.label}} is invalid</span>
</div>
</div>
When this gets rendered to the screen, the drop downs are aligned correctly, with the correct widths, as you can see:
Now, if I follow Angular's method, my main code block will now become:
<div class="row">
<app-question *ngFor="let question of questions" [question]="question" [form]="form"></app-question>
</div>
And my app-question component has the following code:
<div [formGroup]="form">
<div class="col-{{question.colType}}-{{question.colWidth}} form-group">
<label for="{{question.key}}">{{question.label}}</label>
<span [ngSwitch]="question.controlType">
<select *ngSwitchCase="'dropdown'"
[id]="question.key"
[formControlName]="question.key"
[className]="question.fieldClass"
>
<option *ngFor="let opt of question.options" [ngValue]="opt.value">{{opt.name}}</option>
</select>
</span>
<span class="help-block error" *ngIf="isFormTouchedAndInvalid(question.key)">{{question.label}} is invalid</span>
</div>
</div>
When the form renders to the screen it looks like this:
As you can see, the column widths are gone. I'm certain it has something to do with the div tag holding the FormGroup attribute, but that is required for the component to compile and work. I've tried adding it with a span tag, adding the col-md-6 class to the same tag as FormGroup, but I get the same, incorrect CSS rendering.
Is this another Bootstrap 4 issue where I may need to go down to Bootstrap 3 for this to work? If not, what is going on and how can I get the page to correctly render like the first image and yet still be able to use the app-question component in my code?
I believe that the problem is that Angular renders app-question component as a tag <app-question></app-question> and your div tags inside of it have styles relative to that app-question tag, but not the parent <div class="row">. So if you add a class col-md-6(for example) it will cover 50% of the app-question tag, but not the row one.
So if you want the styles to work, you should add the classes here
<div class="row">
<app-question *ngFor="let question of questions"
[question]="question"
[form]="form"
class="col-md-6">
</app-question>
</div>
As an alternative, you can change your app-question component decorator to make it an attribute.
#Component({
selector: '[app-question]'
})
And then use it to any tag you like
<div class="row">
<div app-question
*ngFor="let question of questions"
[question]="question"
[form]="form"
class="col-md-6">
</app-question>
</div>

ReactJS. The component's state won't change if click is performed on nested html element

So, I have the IssuesList component, which is the list of issues that I get using ajax and github api, and DevStatus component, which sort of wraps the list up and contains all the logic, triggers state changes by two radiobuttons and so on.
My problem: When I click on one of the radiobuttons, the DevStatus component won't change state if the click was on the text inside the radiobutton. And when I click on the corners of the radiobuttons, the blue areas without text, the state changes perfectly.
Here's the structure of the radiobuttons:
<div className="btn-group" data-toggle="buttons">
<label className="btn btn-primary active"
onClick={this.onChangeRadioButton.bind(this)}
id={this.CLOSED_ISSUE_ID}>
<input type="radio" name="options"
autoComplete="off"
id={this.CLOSED_ISSUE_INPT_ID}
onChange={this.onInputChange.bind(this)} /> Closed Issues
</label>
<label className="btn btn-primary"
onClick={this.onChangeRadioButton.bind(this)}
id={this.OPEN_ISSUE_ID}>
<input type="radio" name="options"
autoComplete="off"
id={this.OPENED_ISSUE_INPT_ID}
onChange={this.onInputChange.bind(this)} /> Open Issues
</label>
</div>
Here's the codepen with the code and here's the full page view so you could better see and understand what I'm talking about.
Please, open the full page view and try to click on parts of the button that contain text and on ones that don't and you'll notice that as long as you click on parts without text - the state changes and if you click on text itself - the state doesn't change at all.
Could you please help me with that problem?
PS: removing onChange from the input element is not the solution.
Update 1
If you go to DevTools and inspect the radiobutton element, you'll see that inside the label tag there're input and weird span elements. The span element is not in the code I wrote, did React automatically add that? For some reason, the onClick event listener is not applied to those input and span elements.
Update 2
I've tried to add click event listener to the radiobutton in the console of dev tools and tried to figure out the target of the clicked element. When I click on the text - it is the span element and when I click on place without text - it is the label element and that's why the click event is not working.
Can my problem be solved using dangerouslySetInnerHTML, so that it won't create the unnecessary span?
Could you tell me please how to solve that?
React is creating a span because your text is not in any div. Also it would create a span if there was any white space (but in your case this is because there is no div around your text).
But the real problem here is the way you check your event. You need to check e.currentTarget instead of e.target
Then no need to use the ugly dangerouslysetinnerhtml!
React appeared to sometimes be adding span tags around text, no matter if there are the free white-spaces or not. The spans didn't allow the onClick event to fire when they were clicked on.
So, to force React not to render the spans, the dangerouslySetInnerHTML may be used:
noSpanRender(text) {
return { __html: `<input type='radio' name='options' autoComplete='off'/>${text}` };
}
render() {
return (
<div className="dev-status-page col-centered">
<div className="graphs">
<h1 className="text-center page-header">
Our Recent Closed and Opened Issues from GitHub
</h1>
</div>
<div className="issues col-centered">
<div className="btn-group" data-toggle="buttons">
<label className="btn btn-primary active"
onClick={this.onChangeRadioButton.bind(this)}
id={this.CLOSED_ISSUE_ID}
dangerouslySetInnerHTML={this.noSpanRender('Closed Issues')} />
<label className="btn btn-primary"
onClick={this.onChangeRadioButton.bind(this)}
id={this.OPEN_ISSUE_ID}
dangerouslySetInnerHTML={this.noSpanRender('Open Issues')} />
</div>
<IssuesList issues={this.state.issues} />
</div>
</div>
)
}
It was vital to avoid those span elements inside the input tag, so using dangerouslySetInnerHTML finally helped.

How to center input radio

I'm using jquery mobile for my project. It automatically converts all radio buttons in its inputs with its styles. The major problem is that in different situations i have different number of buttons (it depends on user) with its different width and i need it every time center.
<div data-role="fieldcontain" id="inline" >
<fieldset data-role="controlgroup" data-type="horizontal" data-mini="true">
{section name=i loop=$data['input'] start=0}
<input name="position" id="radio{$smarty.section.i.index}" value="{$data['input'][i]}" type="radio" />
<label for="radio{$smarty.section.i.index}">
{$data['input'][i]}
</label>
{/section}
</fieldset>
</div>
As you see each button has his size (for example Up and Zoom In are different). As i said before - i don't know what buttons will be for each users - it depends on their own settings, so i need somehow automatize process of centering it - is some ideas?
You could try it with <a> instead of <input> as done in the documentation, if at all possible in your situation.

Select the containing div of selected radio button

With the following markup:
<div class="paymentOption">
<input type="radio" name="paymentOption" value="1" />
<span class="marginLeft10">1-time payment using a different credit card</span>
</div>
Using CSS only, how do we select the div that contains a selected radio button? (is this possible?)
This is currently impossible with CSS. You can use jQuery though:
http://api.jquery.com/has-selector/

Resources