How can I create a text link in a Knockout JavaScript table? - javascript

I've got some KnockoutJS code working - it pulls in a list and binds it to a table.
For the table-data which displays the name, I would like that to be an <a href=...>, but not sure how. The name is still displayed. But you can click on it.
Here's my current code:
<tbody data-bind="foreach: items">
<tr>
<td data-bind="text: name()"></td>
<td data-bind="text: price()"></td>
<td data-bind="text: endsOn()"></td>
</tr>
</tbody>
nothing too crazy.
I have another property called url which contains the full http://blah URL to direct the users to. Also, I would like a new tab to open up.
Any suggestions?

You have to remove data-bind attribute from td tag and put a with attr binding inside td:
<tbody data-bind="foreach: items">
<tr>
<td><a data-bind="text: name, attr: {href: url}" target="_new"></a></td>
<td data-bind="text: price"></td>
<td data-bind="text: endsOn"></td>
</tr>
</tbody>
P.S. You don't have to put () after property name in data-bind attribute if you don't construct expression.

Related

How do I hyperlink with ng-href in <td> elements?

I have a table, and for one of the columns, I'm trying to hyperlink a url using a single word, like "Here". However, the column is showing up as blank (as well as getting an "attribute ng-href not allowed" warning on intelliJ. This is what the table looks like, with the last line being my attempt to hyperlink:
<tr>
<td ng-bind="order.paid | date:'short'"></td>
<td ng-bind="order.totalQty"></td>
<td ng-bind="order.total.pretty" ng-if="!store.shopifyInstalled"></td>
<td><a ng-href="order.shopifyReceiptUrl" ng-bind="Here" ng-if="store.shopifyInstalled"></a></td>
</tr>
What am I doing wrong?
Use the curly braces {{}} to put your model and remove the ng-bind directive.
<tr>
<td ng-bind="order.paid | date:'short'"></td>
<td ng-bind="order.totalQty"></td>
<td ng-bind="order.total.pretty" ng-if="!store.shopifyInstalled"></td>
<td><a ng-href="{{order.shopifyReceiptUrl}}" ng-if="store.shopifyInstalled">Here</a></td>
</tr>
Can be Done in Two Ways:
First defining a var with ng-init:
<td><a ng-href="order.shopifyReceiptUrl" ng-bind="var_name" ng-init="var_name='Here'" ng-if="store.shopifyInstalled"></a></td>
Second Using custom Text:
<td><a ng-href="order.shopifyReceiptUrl" ng-if="store.shopifyInstalled">HERE</a></td>

knockout attribute data binding not working

When I just data-bind one of the attributes, they work. But when I combine them with attr, they don't work. Knockout 3.4.2
<table data-bind="foreach: listPlaces">
<tr>
<td>
<button data-bind="attr: {click: $parent.onClick, text: marker.title}"></button>
</td>
</tr>
</table>
marker.title just shows a string, and onClick opens an info window in google maps.
Your binds should be made like so
<table data-bind="foreach: listPlaces">
<tr>
<td>
<button data-bind="click: $parent.onClick, text: marker.title"></button>
</td>
</tr>
</table>
First of all the text binding should NOT be withing the attr tags, as it is an internal bind used by knockout to update the content of your element and it is expected to work like that.
Now for the click handler, the above is the correct way to attach a click handler, maybe you could get away with an attr: { onClick : 'MyFunc'} but i both doubt it and dont recomend it!

display nested arrays in knockout.js

I have a json object returned via jquery ajax from an asmx service. When I attempt to display it in a table, nothing displays. What might I be doing wrong?
Thanks in advance.
The returned json is ...
[{\"id\":1488,\"name\":\"Baby Books\",
\"categories\":
[{\"id\":152,\"name\":\"Activity Books\",\"value\":\"Ignore\"},
{\"id\":167,\"name\":\"Bedtime and Dreams\",\"value\":\"Ignore\"}]},
{\"id\":1489,\"name\":\"Story Books\",
\"categories\":
[{\"id\":1506,\"name\":\"Games - Floor Puzzles\",\"value\":\"Ignore\"}]}]
the js display code is (where gorupJson is returned from the call) ...
var viewModel = {
groups: ko.observableArray([]),
};
viewModel.groups(groupJson)
ko.applyBindings(viewModel);
the page content is ...
<table width="100%" >
<tbody data-bind="foreach: groups" style="width:100%">
<tr>
<td data-bind="text: name"></td>
<td>
<ul data-bind="foreach: categories">
<li>
<a><span data-bind="text: name"></span></a>
</li>
</ul>
</tbody>
</table>
Your json is not automatically converted into ko collection.
So you need to apply a mapping to this conversion, probably like this ko.mapping.fromJS(data). When you do it, your fields id, name, value will become in ko.observable
If you want to know more about mapping plugin in knockout, take a look at http://knockoutjs.com/documentation/plugins-mapping.html
First, your JSON is invalid.
Check out the fiddle: http://jsfiddle.net/YNdmh/
var groupJson = [{"id":1488,"name":"Baby Books","categories":
[{"id":152,"name":"Activity Books","value":"Ignore"},
{"id":167,"name":"Bedtime and Dreams","value":"Ignore"}]},
{"id":1489,"name":"Story Books","categories":
[{"id":1506,"name":"Games - Floor Puzzles","value":"Ignore"}]}]
You're missing closing tags for <td> and <tr>
The slashes in json have to go aswell.
http://jsfiddle.net/yhBvr/

Adding Operations to Knockout Mapping Object

I am struggling with adding operations to my Knockout Mapping object.
Here is where I am at right now - and I am attempting to follow the Knockout: Mapping API information.
This is the HTML first:
+ Add Contact
<div id="ContactList">
<table>
<thead>
<tr>
<th>ID</th><th>Name</th><th></th>
</tr>
</thead>
<tbody data-bind="foreach: $root">
<tr>
<td data-bind="text: ContactID"></td>
<td data-bind="text: DisplayName"></td>
<td></td>
</tr>
</tbody>
</table>
</div>
And this is my first attempt at wiring up Knockout:
var baseModel = {
addContact: function() {
alert('Woo!');
}
};
contacts = ko.mapping.fromJS('[{"ContactID":6,"DisplayName":"Doe, John"},{"ContactID":7,"DisplayName":"Rogers, Mister"}]', { }, baseModel);
ko.applyBindings(contacts);
Now, if I remove the additional arguments ({} and baseModel) from the ko.mapping.fromJS, all my data is displayed in the table correctly. However (and as to be expected), I get a binding error with the "Add Contact" link. If I add baseModel back in, clicking the "Add Contact" link works, but no data displays. I get no errors one way or another, so I'm a bit stumped on what's going on there.
I'm new to KO, so I feel like I'm missing something pretty simple. I've searched across StackOverflow, but, at this point, I'm just plugging code in to see what works and not actually understanding what is happening here. Can someone provide some additional explanation and point me in the right direction? Thanks.
You're using ko.mapping.fromJS but you're passing a string, not an object/array. Either use fromJSON or pass in a real array.
Also, you should applyBindings on baseModel, and contacts should be a field of the VM. Then you can use foreach: contacts instead of your weird foreach: $root.
See fiddle with those changes: http://jsfiddle.net/antishok/kR4jc/3/
EDIT - Updating your answer with your code so the question can stand on its own.
JavaScript
var baseModel = {
addContact: function() {
alert('Woo!');
}
};
baseModel.contacts = ko.mapping.fromJSON('[{"ContactID":6,"DisplayName":"Doe, John"},{"ContactID":7,"DisplayName":"Rogers, Mister"}]');
ko.applyBindings(baseModel);​
HTML
+ Add Contact
<div id="ContactList">
<table>
<thead>
<tr>
<th>ID</th><th>Name</th><th></th>
</tr>
</thead>
<tbody data-bind="foreach: contacts">
<tr>
<td data-bind="text: ContactID"></td>
<td data-bind="text: DisplayName"></td>
<td></td>
</tr>
</tbody>
</table>
</div>​

Select cell in html table generated by foreach

please help me with knockout.js code
I try select element in table by id and change it's css style, but all rows have same id and I can't using function getElementById. How I can do this simple thing ?
<tbody data-bind="foreach: times">
<tr>
<td id=$index() data-bind="click: $root.select.bind($data, $index(), 0)> </td>
....
<td id=$index() data-bind="click: $root.select.bind($data, $index(), 19)> </td>
<tr>
</tbody>
Try to use such code:
<tbody data-bind="foreach: times">
<tr>
<td data-bind="attr: {id: $index()}, click: $root.select.bind($data, $index(), 0)></td>
<tr>
</tbody>
Read more about attr binding here: http://knockoutjs.com/documentation/attr-binding.html
Id's should always be unique. Assign the same class to all elements you're interested in and use a bit of jquery:
document.getElementsByClassName('class_name')
EDIT: Good point. I was originally going to suggest using jquery and then remembered this function. If you are using jquery library, you can also try this:
$('.class_name').each(function(index) {
...do something...
});
EDIT: to answer your question, there are a few ways to do this:
$('.class_name').attr('id', new_id)
or
$('.class_name').addClass('class_name')
depending on what exactly you're trying to do

Categories

Resources