knockout.js foreach binding within table [duplicate] - javascript

This question already has an answer here:
Knockout.js containerless "foreach" not working with <table>
(1 answer)
Closed 9 years ago.
I am new to knockout.js and trying to figure why the next code yields exception, while seeming to be valid knockout binding.
<table>
<!-- ko foreach: [] -->
<tr></tr>
<!-- /ko -->
</table>
jsFiddle: http://jsfiddle.net/Esfk5/

Putting it into a <tbody> seems to resolve the error. Fiddle here, but to summarize the HTML is:
<table>
<tbody>
<!-- ko foreach: [] -->
<tr></tr>
<!-- /ko -->
</tbody>
</table>

Related

Get multiple Angular.js controllers for multilple <td> within the same <tr>

I'm trying to add multiple angular controllers within the same tr tag, the problem is that chrome rewrites the table to standardize it, and there is no element between tr and td in the HTML table hierarchy.
Here is what I currently have, each color represents a different controller to call.
The final aim is to have a table like below, with a different controller for one or multiple td, instead or multiple trs
I know I could use a global controller to handle all the data, or use multiple div elements with a fixed width to achieve this, but I'd prefer using a single tr table.
Here is the code :
<table>
<tr>
<div ng-controller="testController">
<td>{{testcontrollerscopevalue}}</td> <!-- empty when displayed -->
<td>{{testcontrollerscopevalue2}}</td> <!-- empty when displayed -->
<td>{{testcontrollerscopevalue3}}</td> <!-- empty when displayed -->
</div>
<div ng-controller="testController2">
<td>{{testcontroller2scopevalue}}</td> <!-- empty when displayed -->
</div>
</tr>
</table>
The following works :
<table ng-controller="testController">
<tr>
<td>{{testcontrollerscopevalue}}</td> <!-- set when displayed-->
</tr>
</table>
Here is what chrome generates :
<body>
<div ng-controller="testController"></div>
<div ng-controller="testController2"></div>
<table>
<tbody>
<tr>
<td>{{testcontrollerscopevalue}}</td> <!-- out of scope-->
<td>{{testcontrollerscopevalue2}}</td> <!-- out of scope-->
<td>{{testcontrollerscopevalue3}}</td> <!-- out of scope-->
<td>{{testcontroller2scopevalue1}}</td> <!-- out of scope-->
</tr>
</tbody>
</table>
<table ng-controller="testController">
<tbody>
<tr>
<td>{{testcontrollerscopevalue}}</td> <!-- set -->
</tr>
</tbody>
</table>
Is there any way I can achieve this ?
Is there any tag I could use instead of div to get this to work?
Thanks,
As we discussed at length in the chat session, This is a case where you are best served by using the ControllerAs Syntax, and wrapping the <table> element in multiple <div> elements holding each controller's logic.
My suggestion was something similar to the following code:
<div ng-controller="testController as tc">
<div ng-controller="testController2 as tc2">
<table>
<tbody>
<tr>
<td>{{tc1.testcontrollervalue}}</td>
<td>{{tc1.testcontrollervalue2}}</td>
<td>{{tc1.testcontrollervalue3}}</td>
<td>{{tc2.testcontroller2value1}}</td>
</tr>
</tbody>
</table>
</div>
</div>
For this to work, your variables need to be converted to be properties of the controller, rather than properties of $scope.
var tc1 = this; //consistent reference to controller object
SomeService.get(function(data) {
tc1.someProperty = data;
});
You should probably just do:
<td ng-controller="testController2">{{testcontrollerscopevalue}}</td>
If you really need the div:
<td><div ng-controller="testController2">{{testcontrollerscopevalue}}</div></td>

Opposite of jQuery .parents() selector [duplicate]

This question already has answers here:
How to select elements which do not have a specific child element with JQuery
(5 answers)
Closed 8 years ago.
I'm making an userscript for a page. The page is old-school tables-everywhere design. I'm trying to access long table of fields so that they can be filled by script.
The structure can be simplified to be like this:
<form>
<blockquote>
<table>
<tr>
<td>
<table>
<!-- THE DESIRED <input> FIELDS ARE HERE!! -->
</table>
</td>
<td>
<table>
<!-- Contains <select> <input> -->
</table>
</td>
</tr>
</table>
<!-- the table repeats and I need all inner tables -->
</blockquote>
</form>
So I was thinking I could get aAll tables that are in form table but do NOT contain <select>.
I think oposite of the parents selector in jQuery would be ideal. Does something like this exist?
You can try
$('form table table').not(':has(select)');
form table table selects all tables that are in form table, then we excludes items that has a select element
$('form table table').each(function(){
if($(this).find('select').size()==0){
//do something
}
});
another way to do it.

Knockout Binding with Virtual Elements Not Working

I'm working on some custom bindings, and in one I'd like to be able to show a table from some arrays of strings.
fiddle
I simplified it down to this custom binding:
ko.bindingHandlers.table = {
init: function tableBinding(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
element.innerHTML = tableTemplate;
var innerBindingContext = bindingContext.createChildContext(valueAccessor());
ko.applyBindingsToDescendants(innerBindingContext, element);
return {
controlsDescendantBindings: true
};
}
};
This is the contents of template:
<!-- if: head && head.length -->
<thead>
<tr data-bind="foreach: head">
<th data-bind="text: $rawData">not working th</th>
</tr>
</thead>
<!-- /ko -->
<tbody data-bind="foreach: rows">
<tr data-bind="foreach: $data">
<td data-bind="text: $data">not working td</td>
</tr>
</tbody>
And some example data.
ko.applyBindings({
table: {
head: ["Name", "Position"],
rows: [
["John", "Janitor"],
["Mike", "IT"],
["Paul", "HR"],
["Rick", "Coffee Fetcher"]
]
}
});
I'm using Knockout 3.0, however anything that'd work on Knockout 2.x would also work here. If you look at the fiddle, the <thead> part is displaying properly, but the bindings for the body aren't. It works fine if I inline the template, and use a with binding, as in, with: table.
I have to confess, at the moment I am not following all you are doing here, but I can tell enough that your example will work if your if statement uses ko if: instead of just if:.
http://jsfiddle.net/AhLzS/1/
So instead of this:
<!-- if: head && head.length -->
go with this:
<!-- ko if: head && head.length -->
The containerless binding syntax requires <!-- ko ... --> ... <!-- /ko --> as the virtual container. Thus if an html comment syntax just has <!-- if ... -->, knockout does not do anything special.
From the knockout documentation for the "if" binding:
http://knockoutjs.com/documentation/if-binding.html
The <!-- ko --> and <!-- /ko --> comments act as start/end markers,
defining a “virtual element” that contains the markup inside. Knockout
understands this virtual element syntax and binds as if you had a real
container element.

Accessing current Knockout binding context

Take a look at the following code, with a focus on the embedded script:
<tr>
<!-- ko foreach: { data: foos, as: 'f' } -->
<td>
<!-- ko if: f.someCondition() -->
<input id='picker' />
<script type="text/javascript">
$("#picker").kendoDatePicker({
value: new Date(),
change: f.changeFunction }); <!---- note this line -->
</script>
<!-- /ko -->
</td>
<!-- /ko -->
</tr>
See f.changeFunction? I'm getting a JavaScript error that f is not defined. How do I access the current binding context so I can attach the Kendo change handler to my current foo? I've tried using a few of the binding context variables but they aren't accessible outside of the binding expressions. If I can't access the binding context in the embedded script, is there a workaround?
Is there a reason you aren't using the kendo-knockout bindings?
http://rniemeyer.github.io/knockout-kendo/web/DatePicker.html

Achieve fixed column number of a table with data-binding

I have a table with bound data (KnockoutJS) like this:
...
<tr>
<th class="rotated">Row 1</th>
<!-- ko foreach: Dog-->
<td>
<p data-bind="text: Name">
</p>
</td>
<!-- /ko -->
</tr>
...
Problem is that I'd like to have fixed number of columns, for example 5, but sometimes there isn't much data so there are less than 5 columns generated. I'd like to know what is the best way how to add the columns so they are always 5.
I made a Javascript function which goes through all the rows, counts the <td> tags and add <td> tags if needed. Is there other option?
You should always use an array with 5 items even though it has empty values in it.
For example:
var Dog = [{Name:"dog1"},{Name:"dog2"},{Name:""},{Name:"dog3"},{Name:""}];

Categories