Return all rows instead of just one through JavaScript

I am repurposing the script. Currently it only pulls the first row but I need it to pull all rows in the aggregate. I have tried getting it to work but all my changes break it. I need to go through and sum two different fields and then I will do some math with the totals. This currently works with the first line in the aggregate but I need it to total all lines in the aggregate.

Here is the script. 

//COMPONENT NAME is what you put in the custom page element 'component type' property.&nbsp;<br>skuid.componentType.register('TotalMargin',function(element){ &nbsp; &nbsp; &nbsp;<br><br>var $ = skuid.$;<br>var m = skuid.model.getModel('InvoiceLine'); &nbsp;//Name of your model<br>var row = m.getFirstRow(); &nbsp; &nbsp;//Using an aggregate model that only returns one row.&nbsp;<br>//Field name from your aggregate model<br>var cost = row.sumCost;&nbsp;<br>var total = row.sumTotalDue;<br><br><br>var MathValue = &nbsp;(total-cost).toFixed(2); &nbsp;//Do your math here<br>element.append(<br>&nbsp; &nbsp; m.mergeRow(row,MathValue)<br>&nbsp; &nbsp; );<br>});

Tammy,

Try replacing the middle section of your code with something like this:

var $ = skuid.$;<br>var m = skuid.model.getModel('InvoiceLine'); &nbsp;//Name of your model var cost = 0, total = 0;<br>$.each(m.getRows(),function(i,row){ cost += row.sumCost; total += row.sumTotalDue; }); 

Thanks Matt! I tried this before and ran into the same problem I am running into now. I get an error on line 14. Which is the element line. It expects to see “)”

//COMPONENT NAME is what you put in the custom page element 'component type' property.&nbsp;<br>skuid.componentType.register('TestMargin',function(element){ &nbsp; &nbsp; &nbsp;<br>var $ = skuid.$;<br>var m = skuid.model.getModel('InvoiceLine'); &nbsp;//Name of your model<br>var cost = 0, total = 0;<br>$.each(m.getRows(),function(i,row){<br>&nbsp; &nbsp;cost += row.sumCost;<br>&nbsp; &nbsp;total += row.sumTotalDue;<br>&nbsp; &nbsp;<br>MathValue = &nbsp;'Total Margin:' + " " + (cost/total*100).toFixed(0) + '%' ; &nbsp;//Do your math here<br>}<br>element.append(<br>&nbsp; &nbsp; m.mergeRow(row,MathValue)<br>&nbsp; &nbsp; );<br>});

Tammy,

I think you just need to close your .each() loop before you start calculating MathValue.

//COMPONENT NAME is what you put in the custom page element ‘component type’ property. 

skuid.componentType.register('TestMargin',function(element){ &nbsp; &nbsp; &nbsp;<br>var $ = skuid.$;<br>var m = skuid.model.getModel('InvoiceLine'); &nbsp;//Name of your model<br>var cost = 0, total = 0;<br>$.each(m.getRows(),function(i,row){<br>&nbsp; &nbsp;cost += row.sumCost;<br>&nbsp; &nbsp;total += row.sumTotalDue;<br>});<br>MathValue = &nbsp;'Total Margin:' + " " + (cost/total*100).toFixed(0) + '%' ; &nbsp;//Do your math here<br><br>element.append(<br>&nbsp; &nbsp; m.mergeRow(row,MathValue)<br>&nbsp; &nbsp; );<br>});

Thanks for working this through with me. I have it so there are no errors in the code however it breaks the page.


&#47;&#47;COMPONENT NAME is what you put in the custom page element 'component type' property&#46; skuid&#46;componentType&#46;register('TestMargin',function(element){ var $ = skuid&#46;$; var m = skuid&#46;model&#46;getModel('InvoiceLine'); &#47;&#47;Name of your model var cost = 0, total = 0; &#47;&#47;setting variables for the two fields we are summing $&#46;each(m&#46;getRows(),function(i,row){ &#47;&#47;get multiple rows in the model cost += row&#46;sumCost; &#47;&#47;get the cost row and assigning them to the variable total += row&#46;sumTotalDue; &#47;&#47;get the total row and assigning them to the variable }); &#47;&#47;close the each var MathValue = 'Total Margin:' + " " + (cost/total*100)&#46;toFixed(0) + '%' ; &#47;&#47;Do your math here element&#46;append( m&#46;mergeRow(row,MathValue)&#47;&#47;this is what writes to component ); }); &#47;&#47;closes the whole script

How are you calling this?  Is this inline or in a static resource?  is it a custom component or a inline snippett?  The format of the beginning and end of the script will be different in important ways. 

Hi Rob,

This is being displayed in custom component through an inline snippet. I was thinking I had to change the end but wasn’t sure what had to change.


Rob,

I took another stab at it. I don’t get any error but It still doesn’t render. Can you see what I am doing wrong?

JS Script: Inline
Writing to: Custom Component

//COMPONENT NAME is what you put in the custom page element 'component type' property. skuid.componentType.register('TestMargin',function(element){ var $ = skuid.$; var m = skuid.model.getModel('InvoiceLine'); //Name of your model var render = function(){ element.empty(); var row = m.getFirstRow(); //setting variables for the two fields we are summing var cost = 0, total = 0, value = 0; $.each(m.getrows(), function (i, row){ //get multiple rows in the model cost += row.sumCost; //get the cost row and assigning them to the variable total += row.sumTotalDue; //get the total row and assigning them to the variable }); //close the each value = (cost/total*100); var text = 'Total Margin:' + value + '%' element.append( m.mergeRow(row,text)//this is what writes to component ); }; skuid.events.subscribe('models.loaded',function(updateResult){ if (updateResult.models.InvoiceLine) { render(); } }); render(); });<br>




Tami -

If I’m understanding the code correctly, the problem is that you’re “render” method doesn’t actually render anything as the code that does the rendering is in the main function block.  So, what’s occuring is that it appends to the element on the first time through, but then “models.loaded” fires, and element.empty() is called but nothing is ever added back to the element and that is why it appears blank.

Try moving the lines starting with “value = (cost/total*100)” down to “skuid.events” in to the render function itself.

Hope this helps.

Ok, disregard my previous post, you do in fact have the append inside of the render function.  That’s what I get for trying to read the code within the post itself - difficult to line up the “{” and “}” :slight_smile:

Couple of things:

1) It does appear that you are missing a semi-colon after the “var text = …” line so I’d recommend adding that in.
2) m.getrows() should be m.getRows().

Beyond that, here is what I would try:

1) Check the console to make sure there are no javascript errors
2) Use the “Source” panel in the console to mark a breakpoint in the code on the first line itself, on the first line of the render function and on the first line of the subscribe function.  
3) Run the page to see where the breakpoints are getting hit
4) Assuming all 3 breakpoints are hit, walk through the code to see where it’s going awry

Hops this helps!

Hey Barry,

Thank you for all your help.

I am getting the script to render now but I am getting a “NaN”.

So I went into the console to see where it is breaking. So far it seems like it is breaking at the “total += row.sumTotalInvoice;”.

The Total Invoice field is a double so it seems java is not rendering it as a number.

I tried converting it to a number with Number() or parseInt() but neither worked.

// Total Invoices skuid.componentType.register('TestMargin',function(element){ var $ = skuid.$; var invoiceline = skuid.model.getModel('InvoiceLine'); var render = function(){ var row = invoiceline.getRows(); var total = 0, cost = 0; $.each(invoiceline.data, function (i, row){ cost += row.sumCost; total += row.sumTotalInvoice; //This is what we are writting. Adding all the invoice total fields. }); console.log('Cost' + cost); console.log('Total' + total); //var a = Number(cost), b = Number(total); var value = (a/b*100).toFixed(0); var text = "<div class= 'box ui-widget'><div class='kpi-title'> Total Margin </div><div class = 'kpi'>" + value + '%'; element.append( invoiceline.mergeRow(row,text) ); }; skuid.events.subscribe('models.loaded',function(updateResult){ if (updateResult.models.InvoiceLine) { render(); } }); render(); }); 

So I realized that I was using the wrong alias name, I was using “sumTotalInvoice” when I should have been “sumTotalDue” DUH!!!

The lesson here is check your alias name’s so you don’t spend all night banging your head against the wall.

Here is the final code that worked:

// Total Margin skuid.componentType.register('TotalMargin',function(element){ var $ = skuid.$; var invoiceline = skuid.model.getModel('InvoiceLine'); var render = function(){ var row = invoiceline.getRows();//get rows in model var total = 0, cost = 0; $.each(invoiceline.data, function (i, row){ //loop through rows //adding the rows. use the alias name for the field cost += row.sumCost; total += row.sumTotalDue; }); //debug console.log('Cost' + cost); console.log('Total' + total); var value = (cost/total*100).toFixed(0);//Do Math here var text = 'Total Margin:' +" " + value + '%';//This what gets rendered in component element.append( invoiceline.mergeRow(row,text)//This is writting to the component ); }; skuid.events.subscribe('models.loaded',function(updateResult){ if (updateResult.models.InvoiceLine) { render(); } }); render(); }); <br>



Great news, glad you got it sorted Tami.  

I’m not exactly sure how you are building your models and how rows get populated in those models so one thing you might want to do is make this modification:

$.each(invoiceline.data, function (i, row){ //loop through rows

//adding the rows. use the alias name for the field cost += row.sumCost; total += row.sumTotalDue; });

to

$.each(invoiceline.data, function (i, row){ //loop through rows //adding the rows. use the alias name for the field cost += (row.sumCost || 0); total += (row.sumTotalDue || 0); &nbsp;

});

This will ensure that if/when sumCost or sumTotalDue are ever null/undefined, that you’ll get a zero (0) instead.

Thanks for that tip Barry. I have added your suggestion into the code. This has been a great learning experience for me!

I ran into one problem this morning. I added a filter to the table and when I filter the data the new result in the component is not replaced instead it is added to.

I realized that I was missing “element.empty();”

I added the updated code below. There are tons of comments to help me understand everything that is going on.

** Prior to adding that element this is how the result would display:**


After the data displayed replacing the prior result showing only 1 result:

// Total Margin skuid.componentType.register('TotalMargin',function(element){ var $ = skuid.$; var invoiceline = skuid.model.getModel('InvoiceLine'); var render = function(){ element.empty();//this empties the element so a new value can replace the prior value var row = invoiceline.getRows();//get rows in model var total = 0, cost = 0; $.each(invoiceline.data, function (i, row){ //loop through rows //adding the rows. use the alias name for the field cost += (row.sumCost || 0); total += (row.sumTotalDue || 0); }); //debug console.log('Cost' + cost); console.log('Total' + total); var net = (cost-total).toFixed(0);//Do Math here var margin = (1-net/total\*100).toFixed(0); var text = 'Total Margin:' +" " + margin + '%';//This what gets rendered in component element.append( invoiceline.mergeRow(row,text)//This is writting to the component ); }; skuid.events.subscribe('models.loaded',function(updateResult){ if (updateResult.models.InvoiceLine) { render(); //Displays result on requery } }); render();//Gets result on page load });

Nice work, Tami! We learn by doing.

Yes Tami.  Thanks for sharing!  Welcome to the Dark Side of Javascript.  We have better cookies.