TheRev
TheRev

Reputation: 134

How to use a bindingHandler twice

I have a binding handler for the JSONEditor npm package. My program will enable the user to compare two different JSON files inside those panels. My bindingHandler looks like this:

var editor = undefined;
ko.bindingHandlers.jsoneditor = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        const options = {
            "mode" : "view"
        };
        const value = ko.utils.unwrapObservable(valueAccessor());

        if(!editor) {
            editor = new JSONEditor(element, options);
            editor.set(value);
        }
        else if(element !== editor.container){
            editor = new JSONEditor(element, options);
            editor.set(value);
        }
    },
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {

        const options = {
            "mode" : "view"
        };
        const value = ko.utils.unwrapObservable(valueAccessor());

        if(element === editor.container){
            editor.destroy();
            editor = new JSONEditor(element, options);
            editor.set(value);
        }
        else {
            //editor.set(value);
            editor = new JSONEditor(element, options);
            editor.destroy();
        }

    }
};

The problem with this is that whenever I switch the panels, the element changes, and creating the error with the editor.

Here's the HTML:

<div class="jsoneditor body" id="editor-1" data-bind="jsoneditor: subject1"></div>
<div class="jsoneditor body" id="editor-2" data-bind="jsoneditor: subject2"></div>

Upvotes: 0

Views: 60

Answers (1)

MKougiouris
MKougiouris

Reputation: 2861

First of all, get rid of the editor variable outside the handler - not cool. You don't want a shared instance, what you want is to have a handler manage 2 editor instances at a time, one for each JSON file

ko.bindingHandlers.jsoneditor = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        const options = {
            "mode" : "view"
        };
        const files = valueAccessor();
        const editors = [];

        files.forEach(f =>{
        // create a new element for each subject
        // and append to dom 
        // attach an editor to each created element
        // set your new value 
        var $currentElem = $('<div>');           
        $(element).append($currentElem);                
        editors.push(new JSONEditor($currentElem, options));      
        editors[editors.length-1].set(f); 
        });

    },
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {    
    }
};




<div class="EditorContainer" id="Editor_SmUniqueThingy" data-bind="jsoneditor: { file1: subject1, file2: subject2 }"></div>

This is not a working example, and i have ommited the update entirely, but the concept is this... Pass in the handler the 2 subjects and any options each might need, then inside the handler:

  1. Create the 2 divs that will contain the editors
  2. Set their values from the passed in valueAccessor data
  3. Manage them both with events etc

Upvotes: 1

Related Questions