My Knockout Js seems to behave intermittently

153 views
Skip to first unread message

KEn Rubin

unread,
Mar 28, 2022, 2:41:55 PM3/28/22
to KnockoutJS

We use Knockout.js and MVC in a Webapp and are having an issue, where the order merchandise total observed is 0 by Knockout.js, as displayed in the GUI. The code seems to be working intermittently, because sometimes we do show the merchandise total in other orders. All orders use the same code and a merchandise total non zero value is always seen in the OrderDetailClientViewModel object within the controller before being passed to the view. The view is coded in Knockout.js and plain javascript.

The "Totals" property shown below is an object (Models.OrderTotalViewModel), which contains the "MerchandiseTotal" field, which is sometimes showing a 0. I'm showing the relevant parts of the two view files below. I don't see the merchandiseTotal value being modified erroneously in the code. Only helpful segments are shown below.

Any suggestions to fix this intermittent behavior would be greatly appreciated!!!

Thank you, Ken

--Edit.cshtml
@model Models.OrderEditPageViewModel
...
var rawViewModel = @(Html.ToJson(Model.OrderDetailClientViewModel()));
var viewModel = ko.mapping.fromJS(rawViewModel,
{
'HeaderData': {
                create: function(options) {
                    options.data.StartDate = new Date(options.data.StartDate);
                    options.data.EndDate = new Date(options.data.EndDate);
                    var headerData = ko.mapping.fromJS(options.data);
                    headerData.errors = new HeaderDataError();
                    return headerData;
                }

         },
'Totals':    {
                create: function(options) {
                    var totals = ko.mapping.fromJS(options.data);
                    totals.errors = new TotalsError();
                    totals.isPromoCodeApplied = ko.observable(false);

                    if ($.trim(totals.PromoCode()) !== "")
                        totals.isPromoCodeApplied(true);
                   
                    return totals;
                }
            }
        });

...
-- This segment in Edit.cshtml shows where the OrderTotalViewModel.cshtml is called for Totals.
<tr>
                        <td colspan="3">
                            @Html.EditorFor(m => m.Totals)
                        </td>
                    </tr>


--OrderTotalViewModel.cshtml
@model Models.OrderTotalViewModel
@{ Layout = null; }
...
<td colspan="3" style="text-align:right">
                <table class="PaddedTable" style="width:925px">
                    <tbody>
                        <tr>
                            <td style="width:125px;text-align:right">Merchandise&nbsp;Total:</td>
                            <td style="text-align:right" class="NormalTextBold">
                                @(Html.Knockout().SpanFor(m => m.MerchandiseTotal)
                                    .HtmlAttributes(new { @class = "NormalTextBold" })
                                    .Currency())

LG Song

unread,
Mar 28, 2022, 4:59:20 PM3/28/22
to knock...@googlegroups.com
Since it involves server side code and client side code on the same page, and the error happens intermittently, I think it is likely caused by the order of the code being executed.

For example, in good condition a web request completed in 200 ms, but in some other condition 2 seconds. This will lead to issue like this.

Your code is mixing razor page and JavaScript together, that is pretty challenging to debug.

I would check the network tab of the developer console and watch the order of the web request.
Then simulate slow network connection to see if you can reproduce the issue.

It is better to put web request in a promise chain so that you can be certain when all web requests are over.

Sent from my iPhone

On Mar 28, 2022, at 1:41 PM, KEn Rubin <krubi...@gmail.com> wrote:


--
You received this message because you are subscribed to the Google Groups "KnockoutJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to knockoutjs+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/knockoutjs/b2ff7381-9e76-4657-b84a-437c8c44fd78n%40googlegroups.com.

Julio Di Egidio

unread,
Mar 29, 2022, 12:06:59 PM3/29/22
to KnockoutJS
On Monday, 28 March 2022 at 20:41:55 UTC+2 krubi...@gmail.com wrote:

>  @(Html.Knockout().SpanFor(m => m.MerchandiseTotal)

Is that 'Knockout' method some custom code of yours?  There is no data-binding attribute anywhere otherwise.  Indeed, I'd too start by looking at the generated code in the browser, maybe it's not the code you expect...

But would not think the problem is with timing, since the server side is certainly done by the time the client-side starts running.  So, if this problem is occurring intermittently (and the generated client code is correct), I'd rather check that the data is in fact correct (it is not in fact zero at times): maybe it's querying the db that is failing intermittently (and exceptions are ignored) or something similar?  Anyway, just another guess.

Julio

KEn Rubin

unread,
Mar 31, 2022, 9:07:05 PM3/31/22
to KnockoutJS
Hi,

Thank you for the responses! I have done some more debugging.  The statement @(Html.Knockout().SpanFor(m => m.MerchandiseTotal) is a razor statement that appears to bind the knockout observable value to the GUI. Also when we test we have always seen the non zero quantity in the observable object, but it is not always rendered by the GUI.

When I look at the equivalent HTML, I see the value  shown below. This is seen whether we successfully render the actual value in the working order or not.
In one case we show the $35.00 Merchandise total in the GUI. for the other case we do not show the $75.00 merchandise total, but the HTML looks the same for both. This is observing the Elements menu item in Chrome after selecting F12 and running the scenario.


Any more thoughts would be greatly appreciated.

Thank you,
Ken

HTML
<td style="text-align:right" class="NormalTextBold">
                                <span class="NormalTextBold" data-bind="currency:Totals.MerchandiseTotal"></span>
 </td>

Julio Di Egidio

unread,
Apr 2, 2022, 9:24:29 AM4/2/22
to KnockoutJS
That 'Knockout' method is *not* part of Razor, that's (apparently) a custom *extension method* to Razor's HtmlHelper class, which means it is defined somewhere in your source code, otherwise it's in some external library your code is referencing.  That said, since it seems the html it generates is correct, I'd go back to considering timing issues, just exclusively on the client-side: namely, how/when do you bind your view-model to the page, what else is happening at page load time (e.g. most of the more sophisticated UI frameworks rewrite the DOM at load time), and how do you ensure they play well together (usually you'll want to bind ko as the very last operation in the load chain...).

But a possibly better suggestion, if you won't mind, would be to hire a programmer for an hour to solve it... ;)

Julio
Reply all
Reply to author
Forward
0 new messages