So I figured out a way to do this (hence adding it as an answer), but it feels very very ugly, and I'm sure I'm not using some basic Aura abilities.. so any improvements are more than welcome.
Here's the code:
Component markup:
<aura:component implements="forceCommunity:availableForAllPageTypes" access="global">
<div class="slds-tabs--default">
<ul class="slds-tabs--default__nav" role="tablist">
<li aura:id="tabpage" class="slds-tabs--default__item slds-text-heading--label slds-active" title="Active" onclick="{!c.changeTab}"
role="presentation"><a class="slds-tabs--default__link" href="javascript:void(0);" role="tab" tabindex="0" aria-selected="true" aria-controls="tab-default-1" id="tab-default-1__item">Active</a></li>
<li aura:id="tabpage" class="slds-tabs--default__item slds-text-heading--label" title="Previous" onclick="{!c.changeTab}"
role="presentation"><a class="slds-tabs--default__link" href="javascript:void(0);" role="tab" tabindex="-1" aria-selected="false" aria-controls="tab-default-2" id="tab-default-2__item">Previous</a></li>
</ul>
<div aura:id="tab-default-1" class="slds-tabs--default__content slds-show" role="tabpanel" aria-labelledby="tab-default-1__item">Item One Content</div>
<div aura:id="tab-default-2" class="slds-tabs--default__content slds-hide" role="tabpanel" aria-labelledby="tab-default-2__item">Item Two Content</div>
</div>
</aura:component>
Helper (used to find the div I clicked in):
({
getContainerDiv: function(event, element) {
var elem;
if (!element) {
elem = event.srcElement;
}
else {
elem = element;
}
if (elem.classList.contains('slds-tabs--default__item')) {
return elem;
}
else {
return this.getContainerDiv(event, elem.parentElement);
}
}
})
JS Controller (main logic):
({
changeTab: function(component, event, helper) {
var clickedTab = helper.getContainerDiv(event, null);
var tabs = component.find('tabpage');
for(idx = 0; idx < tabs.length; idx++)
{
tab = tabs[idx].elements[0];
$A.util.removeClass(tab, 'slds-active');
$A.util.removeClass(component.find(tab.children[0].getAttribute('aria-controls')), 'slds-show');
$A.util.addClass(component.find(tab.children[0].getAttribute('aria-controls')), 'slds-hide');
}
$A.util.addClass(clickedTab, 'slds-active');
$A.util.addClass(component.find(clickedTab.children[0].getAttribute('aria-controls')), 'slds-show');
$A.util.removeClass(component.find(clickedTab.children[0].getAttribute('aria-controls')), 'slds-hide');
}
})
In Lightning I would be much more inclined to create this list through an aura:iteration
at the component markup level, bound to an array that you can set, rather than appending strings to innerHTML
. However if you still want to do it this way...
The innerHTML
property is a string, not a reference. You are assigning it to a variable, building it up and then never sending it back. (Unless you have left out part of your code?) So try...
var family=actionResult.getReturnValue();
var famLength=family.length;
var listDOM = document.getElementById("familyList");
var j= '';
j=j+'<li id="menu-40-0" class="slds-dropdown__item"> <a href="javascript:void(0);" role="menuitemradio"> <p class="slds-truncate">';
j=j+'<c:svg ariaHidden="true" class="slds-icon slds-icon--selected slds-icon--x-small slds-icon-text-default slds-m-right--x-small" xlinkHref="/assets/icons/utility-sprite/svg/symbols.svg#check"/>';
j=j+family[0]+'</p> </a> </li>"';
listDOM.innerHTML += j;
Also if you are not familiar with the shorthand increment/concatenation operator +=
, in JavaScript j = j + (expression)
can be written more compactly as j += (expression)
.
Also be aware that inserting c:svg
into the markup is probably not going to work because Lightning XML is converted to scripted elements at the server level and not at the browser level.
So what would a more data-based Lightning solution look like? Well in your markup you could have something like:
<aura:attribute name="family" type="String[]" />
<ul>
<aura:iteration items="{!v.family}" var="item">
<li class="slds-dropdown__item">
<a href="javascript:void(0);" role="menuitemradio">
<p class="slds-truncate">
<c:svg ariaHidden="true" class="slds-icon slds-icon--selected slds-icon--x-small slds-icon-text-default slds-m-right--x-small" xlinkHref="/assets/icons/utility-sprite/svg/symbols.svg#check"/>
{!item}
</p>
</a>
</li>
</aura:iteration>
</ul>
And then your controller would simply populate the array:
component.set('v.family', actionResult.getReturnValue());
Or merge the new items into an existing array, creating a new one if none is there:
var family = component.get('v.family') || [];
var newFamily = family.concat(actionResult.getReturnValue());
component.set('v.family', newFamily);
Best Answer
Can you try this fiddle and let me know?
https://jsfiddle.net/8uufaLhf/1/
In this fiddle I have hidden the my div content when the user clicks out of div.