How to include form field attributes based on state in React? - javascript

I am trying to make an accessible form in React and I need to toggle the attribute aria-describedby based on the state of the field (i.e., if it has an error associated with it).
I know how to toggle the value of the attribute, but with regards to WCAG, a present but empty attribute of this type will fail. The entire attribute needs to be fully present or fully absent. Anything I try in-line throws errors and breaks the render.
To give an example, this is what I've been trying:
<label>
<input type="text" name="someName" ref="someRef" {!this.state.isValid ? aria-describedby="helperText" : ''} required />
<p id="helperText">Helper text for this form field.</p>
</label>
Again though, an empty attribute value for aria-describedby is invalid.
Is there any way to acheive this?

Just spread it like this:
<input type="text"
name="someName"
ref="someRef"
{... !this.state.isValid && {'aria-describedby': 'helperText'} }
required />
This is basically spread operator usage.

Related

v-model depending on conditions [duplicate]

I have a vue component that shows a form populated with items from a selected item to edit. Now I don't want to have to use a second form for creating a new item. At the moment I auto populate and update the item with v-model which obviously updates the object. Am I not able to use conditional operators in this like so?
<form #submit.prevent>
<div class="field">
<label class="label">Job Title</label>
<p class="control">
<input type="text" class="input" placeholder="Job title" v-model="experiences[editIndex].title ? experiences[editIndex].title : ''" />
</p>
</div>
</form>
You can use conditional operators with v-model, but you can't give v-model a string like you're attempting in your example.
I wouldn't use the same form for editing and creating (might be preference). I would make the form its own component and then make two additional form components for editing and creating.
However, if you really want to handle the logic in each input's v-model directive, you would need to give it a variable in the last part of the ternary operator. Something like this:
v-model="experiences[i].title ? experiences[i].title : newExperience.title"
If you use eslint-plugin-vue it will complain about ternary in v-model.
ESLint: 'v-model' directives require the attribute value which is
valid as LHS. (vue/valid-v-model)
So I'd rather explicitly use a pair of :value and #input props.
Like that:
<input
type="text"
class="input"
placeholder="Job title"
:value="experiences[editIndex].title ? experiences[editIndex].title : ''"
#input="experiences[editIndex].title = $event.target.value"
/>
Also, you can use some function for #input, which will check property existence and add it if necessary.

JavaScript: Documentation for access of form, via form name [duplicate]

I am reworking on a code of an old developer and I'm trying to do a form for reservation.
I've looked across the whole code the only thing called reservation is the name and the id of the form.
Form who's is in style : display:none ...
So two question in one : First of all what the heck is supposed to do
document.reservation.submit(); Is it suppose to get the form by his name ?
Shouldn't it be something like document.getElementById('reservation').submit() instead ?
And my second question is : How the form can be sent if all the value are set to display:none I tough it couldn't work and if you want to hide them you shall use hidden property...
I need a bit of help on this guys pls :)
Form for beter comprehension :
<form name='reservation' action='http://xxxx/reservationFormAction.to' method="POST" id="reservation">
<input type="hidden" id="productLive" name="product" value="{$product.info.code}"/>
<input type="hidden" name="complementaryParameters" value=""/>
<input type="text" name="depCityCode" id="depCityCode" style="display:none" />
<input type="text" name="dateDep" id="dateDep" style="display:none" />
<input type="text" name="nightDuration" id="nightDuration" style="display:none" />
<input type="text" name="dayDuration" id="dayDuration" style="display:none" />
<input type="text" name="provider" value="{$product.tourOperator.code}" style="display:none" />
<input type="text" id="toProduct" name="toCode" value="{$product.info.toProductCode}" style="display:none" />
<input type="text" name="catalogCode" value="{$product.info.code}" style="display:none" />
{if $ecall}
<input type="text" name="reservationProfileChannelCode" value="ECALL" style="display:none" />
{else}
<input type="text" name="reservationProfileChannelCode" value="ADV" style="display:none" />
{/if}
<input type="text" name="nbAdults" id="nbAdults" style="display:none" />
<input type="text" name="nbChildren" id="nbChildren" style="display:none" />
<input type="text" name="nbBabies" id="nbBabies" style="display:none" />
<input type="text" name="productUrl" id="productUrl" style="display:none" value="http://www.xxxx.com/{$product.slug}_{$product.info.code}.html" />
<input type="text" name="homeUrl" id="homeUrl" style="display:none" value="http://www.xxxx.com" />
<span id="ageChild" style="display:none"></span>
<div class="update-search clearfix">
document.reservation gets the HTMLFormElement for the form with the name reservation. Then calling submit submits the form (without triggering the submit event).
So why not document.getElementById? That would also work, but document.reservation works because the document object gets various properties created on it automagically, including properties referring to forms by their name. This is covered in ยง3.1.3 of the HTML5 spec *(you have to scroll down a fair bit):
The Document interface supports named properties. The supported property names at any moment consist of the values of the name content attributes of all the applet, exposed embed, form, iframe, img, and exposed object elements in the Document that have non-empty name content attributes, and the values of the id content attributes of all the applet and exposed object elements in the Document that have non-empty id content attributes, and the values of the id content attributes of all the img elements in the Document that have both non-empty name content attributes and non-empty id content attributes.
The value of those properties is the element the name or id came from.
The window object also gets properties for every element with an id, as described here:
The supported property names at any moment consist of the following, in tree order, ignoring later duplicates:
the browsing context name of any child browsing context of the active document whose name is not the empty string,
the value of the name content attribute for all a, applet, area, embed, form, frameset, img, and object elements in the active document that have a non-empty name content attribute, and
the value of the id content attribute of any HTML element in the active document with a non-empty id content attribute.
Where again the value of those properties is the element the name or id came from.
In both cases, this is the HTML5 specification standardizing the previously-widespread-but-nonstandard practice most browsers had, which is widely used on pages in the wild.
How the form can be sent if all the value are set to display:none I tough it couldn't work and if you want to hide them you shall use hidden property...
It's best to ask one question per question.
The CSS display property has no effect at all on whether form fields are submitted; you're probably thinking of the field's disabled state: Disabled form fields are indeed left out of the form on submission.
the display none or hidden info will always be sent even that you can't see.... Usually we pass some info that the user doesn't need to know, like USER_ID=20 .....---- and the
document.reservation.submit
------- it submits the form with name="reservation"

How can I use setAttribute on an input without an ID or class attribute?

I have a search input tag that is being added by a jQuery plug-in:
<input type="search" />
Note that this does not have an ID, CLASS, or NAME. I need the search input tag to look like this:
<input type="search" name="myname" />
A simple solution is for me to update the jQuery plug-in. However, I do not want to do this as it will cause challenges when I upgrade this plug-in in the future.
This JavaScript works properly and adds the name attribute:
$(document).ready(function() {
document.getElementsByTagName("input")[0].setAttribute("name", "myname");
});
The problem is that the "[0]" in this function relies on the search input being the first input field in the form. I do not think this solution is sustainable.
There are other inputs in the form. This is the only one with the type attribute equal to "search." Is there a way to identify it by this attribute? Or, is there another solution you propose?
Thank you for your time!
You can use the document.querySelector:
document.querySelector("input[type='search']")
Below is an example (you can inspect the output to see name attribute):
document.querySelector("input[type=search]").setAttribute("name", "myname");
<input type="search" value="foo" />
<input type="bar" value="bar" />
You can target a selection by anything. So, the selector input[type="search"]' will work.
If you want to apply this to all input's of type search, this is good enough, and you get all of them in here:
$('input[type="search"]')
This works without jQuery too:
document.querySelectorAll('input[type="search"]')
A more targeted approach would be
document.querySelectorAll('div.filter input[type="search"]')

Using the for attribute in JSX - linter unknown property "for"

I have a label with an input. I want to make the whole label area clickable to trigger the input (a checkbox). So I have used the for attribute as I believe this is exactly what it is intended for:
<label for={id}>
<input
name="checkbox"
type="radio"
data-id={id}
/>
</label>
Functionally this works but the linter does not like it:
error Unknown property 'for' found, use 'htmlFor' instead react/no-unknown-property
htmlFor does not appear to have the same functionality as the for attribute.
How can I change my code to make it work whilst retaining the functionality of for - I'd rather avoid writing a custom function that selects the correlating checkbox when you click on the label when that functionality already exists with for
Nothing special you need to do.Try This,
<input
name="checkbox"
type="radio"
data-id={id}
/>
<label htmlFor={id}></label>
Just replace for with htmlFor.
As in React class becomes className, for becomes htmlFor.
If you do document.getElementById you will have to access for property as label.htmlFor, as under the hood JavaScript uses htmlFor.
You can read about it here : prop_label_htmlfor, React htmlfor
Eslint suggestion for reference :

Setting a label's for attribute to a DOM element, not an ID in jQuery

Short Question:
How do you link a label element to an input element without using the input element's id using jQuery and javascript?
Long Question:
I am using jQuery to clone a form with possibly more than one instance of the form being available for the user to fill in.
A label's 'for' attribute is supposed to be set to the 'id' attribute of the input element that it is for. This works when the input element has a unique id.
Because I am cloning the same input element there will be multiple input elements with the same id in the document. Therefore I'm avoiding having id attributes for input elements but I'd still like to focus on the input element when the label is clicked. I also want to avoid generating random ids for fields or setting onclick events on labels.
Edit #1
Example mark up (note no ids)
<form>
<label>First Name:</label><input type='text' name='FirstName' /><br/>
<label>Last Name:</label><input type='text' name='LastName' /><br/>
</form>
Example cloning code:
var newForm = $('form').clone();
$(newForm).find('label').each(function(){
var inputElement = $(this).next('input');
// I'd love to set the label's for attribute to an element
$(this).attr('for', inputElement);
});
$(document).append(newForm);
Edit #2
There currently are three options:
Set onclick events for labels to focus on the input field they're for. Criteria for deciding which labels are for which inputs can be the next input element or something else
Embed the input fields in the label fields (might not be possible due to designer's choices)
Generate random ids while cloning each form
Well it would be nice to see the markup, but if i can assume that the markup will look somewhat like this
<form name="f1">
<label>this is my label</label>
<input />
<label>this is my other label</label>
<input />
</form>
<form name="f2">
<label>this is my label</label>
<input />
<label>this is my other label</label>
<input />
</form>
then you could do something like this
$('form label').live('click',function(){
$(this).next('input').focus();
});
you will need to use live or delegate since you're cloning the forms on the fly i'm assuming.
The simplest solution is to move the <input> tags inside the <label> tags and forgo the for attribute altogether. Per the HTML spec, <input> tags without for attributes are implicitly associated with their contents.
Try this:
<form>
<label>First Name: <input type='text' name='FirstName' /></label><br/>
<label>Last Name: <input type='text' name='LastName' /></label><br/>
</form>
(See: http://www.w3.org/TR/html401/interact/forms.html#h-17.9.1)
You shouldn't have multiple identical ids in the page. It defeats the purpose of the id attribute and is against the W3C spec.
Regardless, jQuery's $(this) could help you in this situation. Say you gave all your the "focusable" class. Then you could do:
$('.focusable').focus( function(){
$(this).doSomething();
});
This is really an HTML question. A label can be associated wtih a form control either by its for attribute having the same value as the associated control's id attribute, or by having the control as a child of the label, e.g.
<form ...>
<label for="nameField">Name:<input id="nameField" name="nameField" ... ></label>
<label>email:<input name="emailField" ... ></label>
</form>
I suppose in jQuery you need something like:
var labelAndInput = $('<label>text<input ... ></label>');
or whatever. Note that older versions of IE (and maybe more recent ones too) the label will not be associated with the control without the for attribute (or htmlFor property), there is no other way.

Categories