When you Push you are pushing a single value.
Your getExpenses
returns a list so you would need to iterate over the results and push each iteration onto expenses.
In the trailhead module, the push is used as part of saveExpense
which returns a single expense which is why pushing the returnValue works.
So when returning a list simply use component.set
if you want to replace all values of expenses or if you want to add to iterate over the results pushing each one
I have not tried it but in principle when returning a list from the controller you should be able to add all values to the attribute using concat as such which would be additive to the existing values.
var expview = component.get("v.expenses");
var parseRes = response.getReturnValue(); //Assuming this is a list
expview.concat(parseRes);
Is it possible to achieve this without using JQuery?
Yes. If you can do something with JQuery, you can do it without JQuery. It's all JavaScript. As an addendum, anything you can do in JQuery you can do without JQuery and get better performance.
In the interest of keeping things brief, I'm not going to write out a full copy of your code with modifications, but a smaller, more generalized example that demonstrates how to do what you're trying to do.
<aura:application >
<aura:attribute name="rows" type="Object[]" />
<aura:handler name="init" value="{!this}" action="{!c.init}" />
<table>
<tbody>
<aura:iteration items="{!v.rows}" var="row" indexVar="rowIndex">
<tr>
<td data-index="{!rowIndex}" onclick="{!c.toggle}">
{!row.Name}
</td>
</tr>
<aura:if isTrue="{!row.expanded}">
<aura:iteration items="{!row.children}" var="child">
<tr>
{!child.Name}
</tr>
</aura:iteration>
</aura:if>
</aura:iteration>
</tbody>
</table>
</aura:application>
({
init: function(cmp, evt) {
cmp.set("v.rows", [
{Name: "A",
expanded: false,
children: [
{ Name: "A1" },
{ Name: "A2" }
]},
{Name: "B",
expanded: false,
children: [
{ Name: "B1" },
{ Name: "B2" }
]},
{Name: "C",
expanded: false,
children: [
{ Name: "C1" },
{ Name: "C2" }
]}
]);
},
toggle: function(cmp, evt) {
var rows = cmp.get("v.rows");
rows[evt.target.dataset.index].expanded = !rows[evt.target.dataset.index].expanded;
cmp.set("v.rows", rows);
}
})
As you can see from this code, it's a trivial matter to simply render the extra rows when the "expanded" attribute has been toggled. You should be able to modify this example to suit your needs.
I've purposefully left out all styling and fluff to get to the heart of the matter, which I think this app demonstrates easily. Most likely, you'll just need to add an "expanded" attribute to your data's information, and then toggle it as appropriate.
There's lots of other things you could do with this as well, such as querying the database, making a callout, or whatever else it is you want/need to do to get the data.
Best Answer
If in the time it took to get the expenses from the server, you switched screens and have unrendered the component that was making the request, the component would have been destroyed.
In this case, you'll still have a reference to that component, but it will no longer be valid.
Simply, checks if the component has been destroyed or not.