1

I am creating html to pass back from a REST method, such as:

StringBuilder builder = new StringBuilder();
builder.Append("<div class=\"row\">");
builder.Append("<div class=\"col-md-6\">");
builder.Append("<div class=\"bottomleft\">");
// TODO: Replace the hardcoded val ("$9,814.81") with the actual val
builder.Append("<h2 class=\"sectiontext\">Forecasted Spend - $9,814.81</h2>");

(the preliminary html has been added prior to this). After that I add live data like so:

builder.Append("<table>");
builder.Append("<tr>");
builder.Append("<th>Item Code</th>");
builder.Append("<th class=\"rightjustifytext\">Last Week's Usage</th>");
builder.Append("<th class=\"rightjustifytext\">This Week's Price</th>");
builder.Append("<th class=\"rightjustifytext\">Forecasted Spend</th>");
builder.Append("</tr>");

decimal forecastedSpend;
int lastWeeksUsage;
int loopCount = 0;
int totalUsage = 0;
decimal totalForecastedSpend = 0.0M;
foreach (DataRow dr in dtViewPriceMatrixVarianceResults.Rows)
{
    builder.Append("<tr>");
    builder.Append(String.Format("<td>{0}</td>", dr["ItemCode"]));
    lastWeeksUsage = ProActWebReportsConstsAndUtils.RandomNumber(1, 1000);
    totalUsage = totalUsage + lastWeeksUsage;
    builder.Append(String.Format("<td class=\"rightjustifytext\">{0}</td>", ProActWebReportsConstsAndUtils.AddThousandsSeparator(lastWeeksUsage, false)));
    builder.Append(String.Format("<td class=\"rightjustifytext\">{0}</td>", ProActWebReportsConstsAndUtils.MoneyFormat(Convert.ToDecimal(dr["Price"]), true)));
    decimal currentPrice = Convert.ToDecimal(dr["Price"]);
    forecastedSpend = lastWeeksUsage * currentPrice;
    totalForecastedSpend = totalForecastedSpend + forecastedSpend;
    builder.Append(String.Format("<td class=\"rightjustifytext\">{0}</td>", ProActWebReportsConstsAndUtils.MoneyFormat(Convert.ToDecimal(forecastedSpend), true)));
    builder.Append("</tr>");
    loopCount++;
    if (loopCount >= 9) break;
}

(I add the total vals to a total row after this). At the end I close the elements and pass back the contents of the StringBuilder:

builder.Append("</table>");
builder.Append("</div>");
builder.Append("</div>");
return builder.ToString();

The problem is that I don't know the value of totalForecastedSpend (which is the value I need to replace teh dummy "$9,814.81" with) until I populate the html table table rows.tabledata. I could do the loop first, and save the values in a generic list for use in the loop, but I'm wondering/hoping if there is a way to replace that value with the real one when I arrive at it, using either html and/or css to accomplish it. Is it possible and, if so, how? Or would "go back to" be considered harmful?

The REST method is:

[Route("{unit}/{begdate}/{enddate}")]
public HttpResponseMessage GetQuadrantData(string unit, string begdate, string enddate)
{
    _unit = unit;
    _beginDate = begdate;
    _endDate = enddate;
    string beginningHtml = GetBeginningHTML();
    string top10ItemsPurchasedHtml = GetTop10ItemsPurchasedHTML();
    string pricingExceptionsHtml = GetPricingExceptionsHTML();
    string forecastedSpendHtml = GetForecastedSpendHTML();
    string deliveryPerformanceHtml = GetDeliveryPerformanceHTML();
    string endingHtml = GetEndingHTML();
    String HtmlToDisplay = string.Format("{0}{1}{2}{3}{4}{5}",
        beginningHtml,
        top10ItemsPurchasedHtml,
        pricingExceptionsHtml,
        forecastedSpendHtml,
        deliveryPerformanceHtml,
        endingHtml);

    return new HttpResponseMessage()
    {
        Content = new StringContent(
            HtmlToDisplay,
            Encoding.UTF8,
            "text/html"
        )
    };
}

The html-generating code at the top of this post is from the GetForecastedSpendHTML() helper method.

Is there a trick I can do to replace "$9,814.81" with the value later assigned to totalForecastedSpend, or am I forced to pursue some other option?

Note: Attempts to add javascript/jQuery have failed (see here, if interested) so I don't know if a javascript solution would help me here.

UDPATE

This doesn't answer my question, but my idea does work, to loop through and make the calculations and save the vals to a generic list first, and use that thereafter:

First, I created this class:

public class ForecastedSpend
{
    public String ItemCode { get; set; }
    public int LastWeeksUsage { get; set; }
    public Decimal Price { get; set; }
    public Decimal ForecastedSpendCalcd { get; set; }
}

...then replaced the code above with this:

int loopCount = 0;
int totalUsage = 0;
decimal totalForecastedSpend = 0.0M;
List<ForecastedSpend> fsList = new List<ForecastedSpend>();
foreach (DataRow dr in dtViewPriceMatrixVarianceResults.Rows)
{
    ForecastedSpend fs = new ForecastedSpend();
    fs.ItemCode = dr["ItemCode"].ToString();
    fs.LastWeeksUsage = ProActWebReportsConstsAndUtils.RandomNumber(1, 1000);
    totalUsage = totalUsage + fs.LastWeeksUsage;
    decimal currentPrice = Convert.ToDecimal(dr["Price"]);
    fs.Price = currentPrice;
    fs.ForecastedSpendCalcd = fs.LastWeeksUsage * currentPrice;
    totalForecastedSpend = totalForecastedSpend + fs.ForecastedSpendCalcd;
    loopCount++;
    fsList.Add(fs);
    if (loopCount >= 9) break;
}

//builder.Append("<h2 class=\"sectiontext\">Forecasted Spend - $9,814.81</h2>");
builder.Append(string.Format("<h2 class=\"sectiontext\">Forecasted Spend - {0}</h2>", ProActWebReportsConstsAndUtils.MoneyFormat(totalForecastedSpend, true)));
builder.Append("<table>");
builder.Append("<tr>");
builder.Append("<th>Item Code</th>");
builder.Append("<th class=\"rightjustifytext\">Last Week's Usage</th>");
builder.Append("<th class=\"rightjustifytext\">This Week's Price</th>");
builder.Append("<th class=\"rightjustifytext\">Forecasted Spend</th>");
builder.Append("</tr>");

foreach (ForecastedSpend fs in fsList)
{
    builder.Append("<tr>");
    builder.Append(String.Format("<td>{0}</td>", fs.ItemCode));
    builder.Append(String.Format("<td class=\"rightjustifytext\">{0}</td>", ProActWebReportsConstsAndUtils.AddThousandsSeparator(fs.LastWeeksUsage, false)));
    builder.Append(String.Format("<td class=\"rightjustifytext\">{0}</td>", ProActWebReportsConstsAndUtils.MoneyFormat(Convert.ToDecimal(fs.Price), true)));
    builder.Append(String.Format("<td class=\"rightjustifytext\">{0}</td>", ProActWebReportsConstsAndUtils.MoneyFormat(Convert.ToDecimal(fs.ForecastedSpendCalcd), true)));
    builder.Append("</tr>");
}

It works just dandy.

Community
  • 1
  • 1
B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862

2 Answers2

1

If you are asking for a way to alter elements order in css/html, it sounds to me like a task for flexible box layout.

Example:

HTML:

<div id="mycontainer">
     <table id="mytable">
        <tr><td>row 1</td></tr>
        <tr><td>row 2</td></tr>
        <tr><td>row 3</td></tr>
        <tr><td>row 4</td></tr>
        <tr><td>row 5</td></tr>
        <tr><td>row 6</td></tr>
        <tr><td>row 7</td></tr>
    </table>
    <p id="mytotal">2000$</p>
</div>

Then, the CSS:

div#mycontainer {
    display: flex;
    flex-direction: column;
}
p#mytotal {
    flex: 1;
    order: 1;
}
table#mytable {
    flex: 1;
    order: 2;
}

Note that I've set the table to appear in 2nd position, and totals to apper in 1st (thorugh the attribute order).

Little Santi
  • 8,563
  • 2
  • 18
  • 46
1

Another -standard- way to transform a result after generating it and before rendering it into the browser is producing an XML result and let the browser transform it with a proper XSL stylesheet.

This technologhy has several advantages:

  • It puts format apart from data, which is generally a good practice.
  • It reduces bandwidth, because the XSL is delivered just once by device (and after, it usually gets cached locally).
  • The transformation is done natively by the browser, which in practice is usually as fast as direct HTML rendering.
  • It helps to maintainability: Shall the format be changed, the server endpoint program has not to be modified at all; just the XSL stylesheet.
Little Santi
  • 8,563
  • 2
  • 18
  • 46
  • I wouldn't necessarily mind doing it that way, but my current problem is retrieving the data to be used when making these transformations. I have previously done this using AJAX calls, but it's not working for me this time. If interested, see http://stackoverflow.com/questions/39297254/why-is-my-rest-method-not-being-called-by-this-jquery – B. Clay Shannon-B. Crow Raven Sep 02 '16 at 21:37
  • So, what is your problem to retrieve the data? I thought about a REST method in the server side that composes an XML with all the needed data, and then an XSL to perform the calculations. Am I wrong? – Little Santi Sep 02 '16 at 21:41
  • Look at the link; it's failing. It doesn't matter at this point whether it returns XML or something else, as it's not even getting reached. – B. Clay Shannon-B. Crow Raven Sep 02 '16 at 21:47