KnockoutJS `with` binding and IE8 - javascript

For some reason my code is generating the error below in IE8, but not in any of the normal browsers.
SCRIPT5022: Unable to parse bindings.
Message: TypeError: 'logoSrc' is undefined;
Bindings value: 'attr': { 'src': logoSrc }
I confirmed that the logoSrc property is indeed defined, even in IE8, right before binding, but still it fails. And disabling the binding to logoSrc just causes the next binding in line to fail.
The html is below. I know I've used a with binding before, so I'm pretty sure that's not the problem, and the html seems to be properly closed.
<div data-bind="visible: mode() === 'print'" class="container-fluid">
<!-- ko with: printVm -->
<div class="row-fluid">
<div class="span12">
<div class="page-header">
<div class="pull-right" style="width:140px;height:60px;overflow:hidden;">
<img data-bind="'attr': { 'src': logoSrc }" src="" />
</div>
<h2>Invoice Statement - <span data-bind="text: itemZeroClientName"></span></h2>
</div>
<strong>Invoice number:</strong> <span data-bind="text: invoiceId"></span>
<strong>Invoice date:</strong> <span data-bind="text: userInfo().invoiceDateDisplay"></span>
<strong>Client number:</strong> <span data-bind="text: itemZeroClientId">22365</span>
<hr />
</div>
</div>
<div class="row-fluid">
<div class="span6 cr-tablet6 cr-phone6">
<h4>Billed by <span data-bind="text: companyNameDisplay"></span></h4>
<span data-bind="html: companyInfo"></span>
</div>
<div class="span6 cr-tablet6 cr-phone6">
<h4>Billed to</h4>
<span data-bind="html: clientInfoDisplay"></span>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<hr />
<table id="printInvoiceTable" class="table">
<thead>
<tr>
<th class="date">Date</th>
<th class="name">Provider</th>
<th class="code">Proc Code</th>
<th class="location">Location</th>
<th class="time">Hours</th>
<th class="units">Units</th>
<th class="charge">Charges</th>
</tr>
</thead>
<tbody data-bind="foreach: items">
<tr>
<td data-bind="text: dateDisplay"></td>
<td data-bind="text: orgName"></td>
<td data-bind="text: procedureCodeString"></td>
<td data-bind="text: location"></td>
<td class="formatted-number" data-bind="text: timeWorkedHrs"></td>
<td class="formatted-number" data-bind="text: (unitsOfService() || 0).toFixed(2)"></td>
<td class="formatted-currency" data-bind="text: (clientCharges() || 0).toFixed(2)"></td>
</tr>
</tbody>
<tfoot>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td class="formatted-number" data-bind="text: totalWorkedHours"></td>
<td class="formatted-number" data-bind="text: totalUnitsOfService"></td>
<td class="formatted-currency" data-bind="text: totalClientRate"></td>
</tr>
</tfoot>
</table>
</div>
</div>
<!-- /ko -->
</div>

As suggested above, it seems the issue is with IE8 removing comments (and thus virtual bindings in some conditions) and has been reported on the knockout forums

I have had issues using with and jquery file upload in IE8. I also had issues with comments and was able to fix it by escaping the comment condition. the knockout webpage mentions this warning.

Related

Vue Component - Rendering in wrong location

I am seeing strange behavior between a vue component and inline template.
Example #1: Inline Template
This is working as expected. The vue component is unchanged as per example #2 below, the only difference is i've copied the template content into the tag as an inline template.
See: https://jsfiddle.net/pobffmnv/
<div class="panel panel-primary">
<div class="panel-heading">Current Clients</div>
<table class="table table-hover">
<thead>
<tr>
<th>Client Name</th>
<th style="text-align: center;">No. Projects</th>
<th style="text-align: center;">Time (7 days)</th>
<th style="text-align: center;">Edit</th>
</tr>
</thead>
<tbody>
<clientlistitem inline-template>
<tr>
<td>Test</td>
<td style="text-align: center;">0</td>
<td style="text-align: center;">0</td>
<td style="text-align: center;">
<div class="btn-group btn-group-xs" role="group">
<button type="button" class="btn small btn-primary">Edit</button>
</div>
</td>
</tr>
</clientlistitem>
</tbody>
</table>
</div>
This correctly shows the following:
Example #2: Not inline
The following is my Vue template. Below is the change to the code to remove the inline template.
See: https://jsfiddle.net/Ld47hoy2/
<template>
<tr>
<td>Test</td>
<td style="text-align: center;">0</td>
<td style="text-align: center;">0</td>
<td style="text-align: center;">
<div class="btn-group btn-group-xs" role="group">
<button type="button" class="btn small btn-primary">
Edit
</button>
</div>
</td>
</tr>
</template>
<script>
export default {
}
</script>
Updated page code:
<div class="panel panel-primary">
<div class="panel-heading">Current Clients</div>
<table class="table table-hover">
<thead>
<tr>
<th>Client Name</th>
<th style="text-align: center;">No. Projects</th>
<th style="text-align: center;">Time (7 days)</th>
<th style="text-align: center;">Edit</th>
</tr>
</thead>
<tbody>
<clientlistitem></clientlistitem>
</tbody>
</table>
</div>
However, with the above, the following is displayed:
Looking at the source code of the output of the page, it appears to have put the rendered code BEFORE my table...? I am expecting this to be between the <tbody></tbody> tags..
Any reason why Vue would output the code to that location instead of the one expected?
The issue here is that with in DOM templates the templates are first rendered by the browser and HTML tables only allow certain kinds of elements inside. That being the case, the component clientlistitem is first rendered outside the table, then Vue compiles the template which results in the component in the wrong place.
To fix that, use the is special attribute.
<tbody>
<tr is="clientlistitem"></tr>
</tbody>
The browser will accept this and render the tr in the correct place, but Vue will interpret it as your component.
Here is your fiddle updated.

Repeat parent row in nested ng-repeat Angularjs?

I have a table which is displaying nested ng-repeat values. The HTML looks like this.
<table class="table">
<thead class="bgThead">
<tr>
<th>Environment</th>
<th>Configurations</th>
<th>Servers</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="environment in serverList.environments" ng-class-odd="''" ng-class-even="'dataTableOdd'">
<td>{{environment.Environment}}</td>
<td ng-repeat="servertypeinfo in environment.ServerTypeInfo">{{servertypeinfo.Type}}</td>
<td ng-repeat="servertypeinfo in environment.ServerTypeInfo">
{{servertypeinfo.ServerConfigInfo.length}}
<td ng-repeat="servers in servertypeinfo.ServerConfigInfo">{{servers.ServerName}}</td>
</td>
</tr>
</tbody>
</table>
Now, when there are multiple values in child ng-repeat, the TDs are getting repeated, instead I want the whole row to be repeated, with the same values, except the new children value. Same goes with further nested ng-repeats. I made a plunk which shows what I am aiming for.
http://plnkr.co/edit/vLw6MCO8NGoFYxaCKeJ0?p=preview
Example without table, may not be what you are looking for
<div class="form-group" ng-repeat="environment in serverList.environments track by $index">
<div class="col-md-4">
<span ng-bind="environment.environment"></span>
</div>
<div class="col-md-8">
<ul class="list-group">
<li id="{{$index}}" ng-repeat="servertypeinfo in environment.serverTypeInfo track by $index">
Server Type: <span style="font-size: 16px;" class="no-margin" ng-bind="servertypeinfo.type">{{servertypeinfo.serverConfigInfo.length}}</span>
<p class="no-margin" ng-repeat="server in servertypeinfo.serverConfigInfo">
Server Name: {{server.serverName}}
</p>
</li>
</ul>
</div>
</div>
use the format like this
<tbody>
<tr ng-repeat="environment in serverList.environments" ng-class-odd="''" ng-class-even="'dataTableOdd'">
<td>
<table>
<tr ng-repeat="servertypeinfo in environment.ServerTypeInfo">
<td>{{environment.Environment}}</td>
<td>{{servertypeinfo.Type}}</td>
<td>
{{servertypeinfo.ServerConfigInfo.length}}
<td ng-repeat="servers in servertypeinfo.ServerConfigInfo">{{servers.ServerName}}</td>
</td>
</tr>
</table>
</td>
</tr>
</tbody>

jQuery .toggle() to not show/hide all within .on 'click'?

I'm actually having the same problem like as in How to prevent jQuery .toggle() to show/hide all within .on 'click' but it didn't help so I'm making my own question.
Is there anyway to prevent toggle to show all but instead show only the neccesary toggle for the user to click? (extra topping -> extra_toppings selected) I did try with my minimum knowledge of using IDs as well this, next(), parents() but with no success.
Here's my code:
JavaScript
$(".extra_topping").click(function() {
$(".extra_toppings").toggle('slow');
});
HTML
(inside a loop over all foods: #foods.each do |food| ...)
<div class="extra_topping">
<a>Click Me!</a>
</div>
<div class="extra_toppings">
<a> Show </a>
</div>
I shortened to original HTML to just this to simplify the problem.
Here are my actual code look like : (without the rails code)
<table class="table">
<thead >
<tr>
<th>Name</th>
<th>Price</th>
<th>Category</th>
<th>Quantity</th>
<th>Actions</th>
<th>Additional Menu</th>
</tr>
</thead>
<tbody>
<tr>
<td>
</td>
<td id="food" style="font-weight:bold;">
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
<div class="extra_topping">
<a>Click me!</a>
</div>
</td>
</tr>
<tr class="extra_toppings">
<td>
</td>
<td colspan="4">
<div class= "mediocre">
<div class= "xaxixo">
<h6>Our Additional Menu</h6>
</div>
<div class="extra_topping">
</div>
<table class="mediocre_table">
<tr>
<td>
<div class="full_mediocre">
<div class="mediocre_collumn">
</div>
</div>
</td>
</tr>
</table>
</div>
</td>
<td>
</td>
</tr>
</tbody>
You could use:
$(".extra_topping").click(function(){
$(this).next('.extra_toppings').toggle('slow');
});
If that was what your markup always looked like, e.g.
<div class="extra_topping">
<a>Click Me!</a>
</div>
<div class="extra_toppings">
<a> Show </a>
</div>
<div class="extra_topping">
<a>Click Me!</a>
</div>
<div class="extra_toppings">
<a> Show </a>
</div>
jsFiddle here.
I'm finally make it work by changing the code from:
$(".extra_topping").click(function(){
$(this).next('.extra_toppings').toggle('slow');
});
into:
$(".extra_topping").click(function(){
$(this).parents('tr').next().toggle('slow')
});
It Works!

Nested containerless foreach in tbody failing for IE

I'm having a bit of trouble getting some nested, containerless foreach bindings to work. It works in grownup browsers, but not IE (8 OR 9).
The closest I could find was this question, but the root of that problem seems to be a lack of a tbody tag, which I have. The error IE is giving is
Cannot find closing comment tag to match: ko foreach: seniors
Sorry for the wall of text, but below is my markup.
<tbody data-bind="foreach: superGroups">
<tr>
<td style="font-weight: bold;" data-bind="text: superName() || 'No Super Set'" colspan="8">
</tr>
<!-- ko foreach: seniors -->
<tr>
<td></td>
<td style="font-weight: bold;" data-bind="text: seniorName() || 'No Senior Set'" colspan="7"></td>
</tr>
<!-- ko foreach: items -->
<tr>
<td>
<span data-bindX="text:superName"></span>
</td>
<td>
<span data-bindX="text:seniorName"></span>
</td>
<td>
<span data-bind="text:clientName"></span>
<i class="icon-tags" data-bind="attr:{title: labels}, visible: labels"></i>
</td>
<td>
<span data-bind="text:description"></span>
</td>
<td>
<span data-bind="visible:superPayAmount">$<span data-bind="text:superPayAmount"></span></span>
<span data-bind="visible:superPayAmount.length == 0">-</span>
</td>
<td>
<span data-bind="shortDate: superStartDate"></span> - <span data-bind="shortDate: superEndDate"></span>
</td>
<td>
<span data-bind="visible:seniorPayAmount">$<span data-bind="text:seniorPayAmount"></span></span>
<span data-bind="visible:!seniorPayAmount.length == 0">-</span>
</td>
<td>
<span data-bind="shortDate: seniorStartDate"></span> - <span data-bind="shortDate: seniorEndDate"></span>
</td>
</tr>
<!-- /ko -->
<!-- /ko -->
</tbody>
You missed closing td tag in the first tr:
<tr>
<td style="font-weight: bold;" data-bind="text: superName() || 'No Super Set'" colspan="8"></td>
</tr>

Knockout.js -- understanding foreach and with

I've been going through the learn.knockout.js tutorials and been experimenting. Can someone explain why this works [Tutorial: Single page applications, Step 2] (using with: chosenFolderData and foreach: mails):
<!-- Mails grid -->
<table class="mails" data-bind="with: chosenFolderData">
<thead><tr><th>From</th><th>To</th><th>Subject</th><th>Date</th></tr></thead>
<tbody data-bind="foreach: mails">
<tr>
<td data-bind="text: from"></td>
<td data-bind="text: to"></td>
<td data-bind="text: subject"></td>
<td data-bind="text: date"></td>
</tr>
</tbody>
</table>
but not this (using just foreach: chosenFolderData.mails):
<!-- Mails grid -->
<table class="mails">
<thead><tr><th>From</th><th>To</th><th>Subject</th><th>Date</th></tr></thead>
<tbody data-bind="foreach: chosenFolderData.mails">
<tr>
<td data-bind="text: from"></td>
<td data-bind="text: to"></td>
<td data-bind="text: subject"></td>
<td data-bind="text: date"></td>
</tr>
</tbody>
</table>
I suspect it's because while chosenFolderData is observable, chosenFolderData.mails is not. Can anyone tell me for certain?
Many thanks!
-- Ralph
Because you are not actually accessing the property you want with the way it is written. In the model chosenFolderData is an observable and must be called like a method to retrieve the value. To provide the functionality without using with (and I suggest not using with where high performance is necessary because of the overhead)...
<tbody data-bind="foreach: chosenFolderData().mails">

Categories

Resources