0

I have the following code (simplified for easy reading) for editing a big grid view. The knockout script will generate hidden edit row for each row. clicking the "Edit" button will unhide the row so users can edit the value. Several html <select> controls have many <option> tags so the generated html is huge.

Is it possible to dynamically insert a editing row after click the "Edit" button? Or is there a better way to handle this common case using knockout/jQuery?

<table>
    <thead>.... </thead>
    <tbody data-bind="foreach: Contacts">
        <tr data-bind="visible: isEditing==false">
            <td><span data-bind="text:Name"></span></td>
            <td><span data-bind="text: Phone"></span></td>
            <td><span data-bind="text: State"></span></td>
            <td><a href="#" data-bind="click: startEdit">Edit</a></td>
        </tr>
        <tr data-bind="visible: isEditing">
            <td>
                First Name:<input data-bind="value: FirstName" />
                Last Name:<input data-bind="value: LastName" />
            </td>
            <td><input data-bind="value: Phone" /></td>
            <td><select data-bind="value: State">...huge options...</select></td>
            <td><a href="#" data-bind="click: updateContact">Done</a></td>
        </tr>
    </tbody>
ca9163d9
  • 27,283
  • 64
  • 210
  • 413
  • A few ideas [here](http://stackoverflow.com/questions/14798370/edit-one-row-in-a-list-of-records/14799380#14799380). – WiredPrairie Feb 11 '13 at 21:12

2 Answers2

1

I would use templates for what you want and put an observable in your view model to return the name of your template. When you click the edit button you change the name of the currentTemplate observable to your edit template and it should swap out your html automagically.

<tbody data-bind="foreach: Contacts">
    <div data-bind="template: currentTemplate"></div>
</tbody>

<script type="text/html" id="contact-view-template">
    <tr>
         <td><span data-bind="text:Name"></span></td>
         ...
    </tr>
</script>

<script type="text/html" id="contact-edit-template">
    <tr>
        <td>
        First Name:<input data-bind="value: FirstName" />
        Last Name:<input data-bind="value: LastName" />
        </td>
        ...
    </tr>
</script>


var Contact = function () {
    var self = this;

    self.currentTemplate = ko.observable( 'contact-view-template' );

    self.onEditClicked = function () {
        self.currentTemplate( 'contact-edit-template' );
        // Some other logic
    };

    self.onSaveClicked = function () {
        self.currentTemplate( 'contact-view-template' );
        // Some other logic
    };
}
Neil
  • 5,179
  • 8
  • 48
  • 87
1

Looking at your code I'm not sure if the startEdit button will display the editing rows for all of the Contacts or just the one you clicked on. If it only makes on editing row appear consider using the If binding instead of Visible.

<tr data-bind="if: isEditing==false">...</tr>
...
<tr data-bind="if: isEditing">...</tr>

When you use Visible the editing row is still there and all the databindings are applied, it's just not visible. By using If the editing row will not exist at all unless isEditing is true. On a big data grid this can make the page load significantly faster.

See knockouts documentation on the If binding for more details http://knockoutjs.com/documentation/if-binding.html

StuartM
  • 136
  • 3