r.pazyaquian
r.pazyaquian

Reputation: 73

Why doesn't Knockout's click-to-edit work in tables and with multiple values?

I've been trying to get Knockout's click-to-edit function in my application. However, it has some really strange behavior when I try and make it work. Specifically, the input doesn't appear when you try to edit on a page with multiple editable values, and all you get with tables is a single input box, regardless of how many objects are in an array. Why does this happen?

Here's the multiple values code:

HTML:

<h1>Job App Tracker</h1>

<div data-bind="foreach: apps">
    <p>
    <b data-bind="visible: !editing(), text: title, click: edit">&nbsp;</b>    
    <input type="text" class="form-control" data-bind="visible: editing, value: title, hasFocus: editing" /> 
    <b data-bind="visible: !editing(), text: description, click: edit">&nbsp;</b>
    <input type="text" class="form-control" data-bind="visible: editing, value: description, hasFocus: editing" /> 
    <b data-bind="visible: !editing(), text: company, click: edit">&nbsp;</b>
    <input type="text" class="form-control" data-bind="visible: editing, value: company, hasFocus: editing" /> 
    <b data-bind="visible: !editing(), text: submit_date, click: edit">&nbsp;</b>
    <input type="text" class="form-control" data-bind="visible: editing, value: submit_date, hasFocus: editing" /> 
    <b data-bind="visible: !editing(), text: link, click: edit">&nbsp;</b>
    <input type="text" class="form-control" data-bind="visible: editing, value: link, hasFocus: editing" />
    </p>
</div>

JS:

// Job app object:
function JobApp(title, description, company, submit_date, link) {
    var self = this;

    self.title = ko.observable(title);
    self.description = ko.observable(description);
    self.company = ko.observable(company);
    self.submit_date = ko.observable(submit_date);
    self.link = ko.observable(link);

    self.editing = ko.observable(false);

    self.edit = function () {
        self.editing(true);
    };
}

// Main KO logic:
function AppViewModel() {
    var self = this;

    self.apps = ko.observableArray([new JobApp('Noodle Picker', 'Picks, noodles, and leaves', 'Noodle Pickers, Inc.', '2014-1-25', 'noodlepickers.com'),
    new JobApp('Not A Real Job', 'Not a real job', 'Not A Real Company', '1969-1-1', 'nope.com')]);

}

ko.applyBindings(new AppViewModel());

And the tables code:

HTML:

<h1>Job App Tracker</h1>    
<table>
    <div data-bind="foreach: apps">
        <tr>
            <td>
                <b data-bind="visible: !editing(), text: title, click: edit">&nbsp;</b>
                <input type="text" class="form-control" data-bind="visible: editing, value: title, hasFocus: editing" />
            </td>
        </tr>
    </div>
</table>

JS:

// Job app object:
function JobApp(title, description, company, submit_date, link) {
    var self = this;

    self.title = ko.observable(title);
    self.description = ko.observable(description);
    self.company = ko.observable(company);
    self.submit_date = ko.observable(submit_date);
    self.link = ko.observable(link);

    self.editing = ko.observable(false);

    self.edit = function () {
        self.editing(true);
    };
}

// Main KO logic:
function AppViewModel() {
    var self = this;

    self.apps = ko.observableArray([new JobApp('Noodle Picker', 'Picks, noodles, and leaves', 'Noodle Pickers, Inc.', '2014-1-25', 'noodlepickers.com'),
    new JobApp('Not A Real Job', 'Not a real job', 'Not A Real Company', '1969-1-1', 'nope.com')]);    
}

ko.applyBindings(new AppViewModel());

Upvotes: 1

Views: 1098

Answers (2)

alexmac
alexmac

Reputation: 19617

The problem was in hasFocus binding. When user clicks by text, all inputs shows, and tried to take focus for yourself! I've deleted hasFocus bindings from inputs and now they are displayed.

I've updated example.

Update

I found a solution how to hide inputs. You can use blur js event. When input will lose focus, all edits will be hidden, and all text will be shown:

<input type="text" class="form-control" data-bind="visible: editing, value: title, event: {blur: stopEdit}" />

Example 2

Upvotes: 1

user1972450
user1972450

Reputation:

You can try a solution like this.

http://jsfiddle.net/eguneys/j4NB4/5/

// Editable Text object:
function EditableText(text, editable) {
 var self = this;
 self.text = ko.observable(text);
 self.editing = ko.observable(editable);
} 

Upvotes: 4

Related Questions