Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot render well-formed html tables using Knockout.js templates

I'm totally delighted with my first experiences with Knockout.js, brilliant library really, but I'm still trying to wrap my head around its templating features, for instance this very simple contacts application, where I'd like to generate a table row for each new contact:

<h3>Contact</h3>

<p>First Name: <input data-bind="value: contactFirstName" /></p>
<p>Last Name: <input data-bind="value: contactLastName" /></p>
<p>Email Address: <input data-bind="value: contactEmailAddress" /></p>

<button data-bind="click: addContact">Add</button>

<table>
<thead>
  <tr>
    <td>First Name</td>
    <td>Last Name</td>
    <td>Email Address</td>
  </tr>
  </thead>
  <tbody data-bind="template: {name: 'contactsTemplate', foreach: contacts}" />
</table>

<script id="contactsTemplate" type="text/html">
  <tr>
    <td>${ $data.firstName }</td>
    <td>${ $data.lastName }</td>
    <td>${ $data.emailAddress }</td>
  </tr>
</script>

<script type="text/javascript">

    function contact(firstName, lastName, emailAddress) {
        return {
            firstName: ko.observable(firstName),
            lastName : ko.observable(lastName),
            emailAddress: ko.observable(emailAddress)
        };
    }

    var viewModel = {
        contactFirstName: ko.observable("Peter"),
        contactLastName: ko.observable("Gibbons"),
        contactEmailAddress: ko.observable("[email protected]"),
        equipments: ko.observableArray([new equipment("Peter", "Gibbons", "[email protected]")]),
        addEquipment: function () {
            this.equipments.push(new equipment("Peter", "Gibbons", "[email protected]"));
        }
    };

    ko.applyBindings(viewModel);

</script>

The bindings are working okay but I'm getting frustrated as it seems is nesting the whole new <tr> within the first <td>. It happens with both Iexplore and Firefox.

Any advice will be sincerely appreciated, thanks much in advance for your guidance.

EDIT

Updated markup to reflect RP Niemeyer contribution.

like image 364
Nano Taboada Avatar asked Feb 05 '26 02:02

Nano Taboada


1 Answers

You can replace this line:

<tr data-bind="template: {name: 'contactsTemplate', foreach: contacts}" />

with:

<tbody data-bind="template: {name: 'contactsTemplate', foreach: contacts}"></tbody>
like image 137
RP Niemeyer Avatar answered Feb 06 '26 15:02

RP Niemeyer