<ui:inputCheckbox/>
always generates the label to the left of the checkbox in the markup, like so:
<ui:inputCheckbox aura:id="reimbursed" label="Reimbursed?" class="slds-checkbox" labelClass="slds-form-element__label" value="{!v.newExpense.Reimbursed__c}" />
becomes
<div class="uiInput uiInputCheckbox uiInput--default uiInput--checkbox">
<label class="slds-form-element__label uiLabel-left form-element__label uiLabel" for="427:2;a">
<span class="">Reimbursed?</span>
</label><input class="slds-checkbox" type="checkbox" id="427:2;a">
</div>
In order to get the pretty checkboxes in SLDS, the checkbox needs to be inside the <label/>
tag, with an additional faux span to do the CSS rendering, like so:
<label class="slds-checkbox" for="checkboxSample1">
<input name="checkbox" type="checkbox" id="checkboxSample1" />
<span class="slds-checkbox--faux"></span>
<span class="slds-form-element__label">Checkbox Label</span>
</label>
In order to achieve this, I need to be able to set the for
attribute on the label to the same value as the aura-generated id
attribute on the checkbox. So I'm trying something like this:
<aura:component implements="force:appHostable" controller="CheckboxTestController">
<aura:attribute name="contacts" type="Contact[]" />
<aura:attribute name="checkedContacts" type="String[]" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<div class="slds-form--stacked">
<fieldset class="slds-form-element">
<span class="slds-form-element__label slds-form-element__label-top">
<legend>Choose contacts to add:</legend>
</span>
<div class="slds-form-element__control">
<aura:iteration var="con" items="{!v.contacts}">
<label for="?????" class="slds-checkbox">
<ui:inputCheckbox class="" text="{!con.Id}" aura:id="{!con.Id}" change="{!c.updateCheckboxes}"/>
<span class="slds-checkbox--faux"></span>
<span class="slds-form-element__label">{!con.Name}</span>
</label>
</aura:iteration>
</div>
</fieldset>
</div>
</aura:component>
The problem I'm having is figuring out how to populate the for
on the label. I'm pretty sure setting {!con.Id}
as the aura:id
on the checkbox isn't working (when I tried a cmp.find('anId') it came back undefined), and I believe this is because only string literals can be used for the aura:id
attribute. And I can't figure out how to get the resulting id
for the for
attribute in the label.
(This is similar to ui:inputCheckbox and lightning design system, but the accepted answer on that question doesn't actually resolve anything – simply removing the app.css stylesheet doesn't make <ui:inputCheckbox/>
reorder the markup.)
Best Answer
It looks like http://documentation.auraframework.org/auradocs#reference?descriptor=ui:inputCheckbox&defType=component , has an attribute called "domId" which sounds like what we want, unfortunately when trying to use it I get
[ERROR]: No ATTRIBUTE named domId found: Source
.However, this attribute is not listed in the ui:inputCheckbox docs located at /auradocs . I guess because it hasn't made it over quite yet.
I'm not sure what
ui:inputCheckbox
really buys us in this situation, as we aren't using the div and label wrappers the component generates (it only seems to do that when we specify a label attribute, which we don't want to do since we want the slds classes and layout).Something like this seems to work for right now:
<label for="{!contact.Id}" class="slds-checkbox"> <input type="checkbox" id="{!contact.Id}" onchange="{!c.checkboxChange}"/> <span class="slds-checkbox--faux"></span> <span class="slds-form-element__label">{!contact.Name}</span> </label>
({checkboxChange: function(component, event, helper){ console.log(event.target.id); })
Problems with this approach:
1) There can be id collisions. A temporary workaround could be adding a namespace to the id.
2) There could also be more built into the ui:inputCheckbox change event than the html5 change event, but the html5 change event seems pretty robust: https://developer.mozilla.org/en-US/docs/Web/Events/change .
Long term, I bet this is problem could be solved by the domId attribute.