solefald
solefald

Reputation: 1799

KnockoutJS: Passing click event data to a div

I need to pass data from a click: event into another div. Here is a scenario:

There is a link on one side of the page.

<a data-bind="text: Name, click: $root.editAction"></a>

On the other side of the page, there is a hidden div.

<div data-bind="if: $root.editActionShow">
    <input type="text" data-bind="value: Name"/>
</div>

I need to be able to pass $data from the click: event, do that hidden div.

Perhaps I am over-thinking this, but my viewModel has many different Actions buried deep in viewModel.DataGroups.DataGroup.ActionDataGroup and there is only 1 HTML form to edit action information, so I can't figure out how to make the form only show that one particular action I want to edit.

Here is another kicker. I prefer not to add any observables to my viewModel. Reason being is that I have to do .toJS() map it at the end, and then convert JSON into XML, which must validate against a pretty strict schema, so having extra elements is a bad thing. It will not pass validation, unless I manually remove them before conversion. However, I can add this.blah = function() {} objects to my viewModel, because .toJS() strips them during conversion.

UPDATE:

Aaand solution to all this is hands down hilarious

viewModel.editAction = function(data) {
    viewModel.editActionFormShow(true);
    ko.applyBindings(data, $('#myHiddenDiv')[0]);
};

Upvotes: 1

Views: 1707

Answers (1)

thomaux
thomaux

Reputation: 19738

From what I understand, you want something like a 'click-to-edit' function, which can be solved pretty neatly with just 2 custom bindings!

The great advantage about this approach is you won't polute your viewModel with extra observables.

Bindings:

ko.bindingHandlers.hidden = {
    update: function(element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        ko.bindingHandlers.visible.update(element, function() {
                return!value; });
        }
    };

ko.bindingHandlers.clickToEdit = {
    init: function(element, valueAccessor,allBindingsAccessor){
        var value = valueAccessor(),
            input = document.createElement('input'),
                        link = document.createElement('a');

        element.appendChild(input);
                    element.appendChild(link);

                    value.isEditing = ko.observable(false);

                    ko.applyBindingsToNode(link,{
                        text: value,
                        hidden: value.isEditing,
                        click: function(){
                            value.isEditing(true);
                        }
                    });

        ko.applyBindingsToNode(input,{
            value: value,
            visible: value.isEditing,
                            hasfocus: value.isEditing
        });
    }
};

ViewModel

var vm = {
    name: ko.observable()
}

The HTML

<div data-bind="clickToEdit: name"></div>

Working fiddle: http://jsfiddle.net/8Qamd/

All credit goes to Ryan Niemeyer.

Upvotes: 1

Related Questions