Knockout fires change event when select list initializing
Asked Answered
H

2

8

I'm having a issue with knockout select list binding, My problem is I'm having a list of items, that contains description,key and editable. using the list of items I'm populating the select box.

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

            self.desc = ko.observable();
            self.key = ko.observable();
            self.editable = ko.observable(false);

            self.requireditemsdata = ko.observableArray([
               { desc: "Boarding of exposed wall openings in the vicinity of ...", key: "233", editable: true },
               { desc: "Call in manufacturers to initiate repairs on ...", key: "242", editable: true },
               { desc: "Call in specialist restorers/recoverers for ...", key: "244", editable: true },
               { desc: "Dispatch items for repair (schedule enclosed)", key: "243", editable: false },
               { desc: "Drying and cleaning of contents comprising ...", key: "240", editable: true },
               { desc: "Drying and protective oiling of water affected equipment", key: "241", editable: false },
               { desc: "Drying out of the affected areas of the premises", key: "235", editable: false },
               { desc: "Removal and repackaging of stock comprising ...", key: "239", editable: true },
               { desc: "Removal of agreed vulnerable contents to a place of safety (schedule enclosed) ", key: "236", editable: false },
               { desc: "Segregation of affected and unaffected stock comprising ...", key: "238", editable: true },
               { desc: "Temporary covering of roof to reinstate water tight integrity ", key: "234", editable: false },
               { desc: "Temporary guarding of affected area", key: "237", editable: false },
               { desc: "Temporary shoring of affected structure", key: "232", editable: false }]);

            self.selectedItem = ko.observableArray([]);

            self.selectedItem.subscribe(function (newValue) {

                if (newValue) {
                    self.editable(newValue.editable);
                    //alert(newValue.editable);
                }
            });

        }

whenever the user select an options from the select list, it contains the property editable,then the select list has to hide from the DOM and text box has to be visible to DOM and the value has to assigned from the selected desc from the select list.

       var RequiredItems = function () {

            var self = this;

            self.requiredItemSelection = ko.observableArray([]);

            self.addRequiredItem = function () {
                self.requiredItemSelection.push(new RequiredItemLine());

            };
            self.removeRequiredItem = function (line) {
                self.requiredItemSelection.remove(line);
            };

        }

        var vm = new RequiredItems();
        ko.applyBindings(vm);

the problem is whenever the select is loading to the DOM change event is firing and display the select list or the input field.

             <div class='liveExample' > 

     <button data-bind='click: addRequiredItem'>Add Required Item</button>
     <hr />

<table width='100%'>

    <tbody data-bind='foreach: requiredItemSelection'  >
        <tr>
            <td >
                <select data-bind='options: requireditemsdata, optionsText: "desc", value: selectedItem'> </select>
            </td>  

            <td>
                <a href='#' data-bind='click: $parent.removeRequiredItem'> <img src="../images/Close.gif" /></a>
            </td>
        </tr>
        <tr data-bind="visible : selectedItem().editable">
            <td>
                <div class="editablecontent" data-bind='html : selectedItem().desc.replace(/\.\.\./g, "<span style=&#39;background-color:#ff77ee;margin-left:-2px;letter-spacing:0.05em&#39; contenteditable >...</span>")'></div>


            </td> 
        </tr> 

    </tbody>
</table>

<ul data-bind='foreach: requiredItemSelection'>


    <li data-bind="text : selectedItem().desc "></li>
</ul>  




</div>

see the fiddle http://jsfiddle.net/aroor/VFv4H/3/ Note: I dont want to use the optionsCaption binding. is there any way to solve this issue? Or didn't i declare the data structure properly ?

Hydrotaxis answered 13/5, 2013 at 12:0 Comment(3)
Can you describe the issue that you are having a little further? Is it that you are seeing the select/input while the page is loading? One trick is to add data-bind="visible: true" style="display: none" to a container element and it will be displayed when the page is bound like: jsfiddle.net/rniemeyer/VFv4H/4Graiae
Sorry English is not my first language.The problem is whenever user select the select list, according to the selected item it contain a property called editable, if the editable is true then display the content editable div with the selected desc and hide the select list.Hydrotaxis
@RPNiemeyer Now i've edited the question, what is in the fiddle. the main purpose is I'm creating a contenteditable div dynamically depend on the selection from the select list.Hydrotaxis
P
1

It will not fire if you set it with a default value.

Write something in optionsCaption. Use this syntax to add a caption:

<select data-bind="options: xxxx, 
                   optionsCaption:'select', 
                   optionsText: yyyy, 
                   value:  jjjjj"> 
</select>

or else you can use optionsCaption as shown below

<select data-bind="options: xxxx,
                optionsCaption: ' ',
               optionsText: yyyy, 
              value:  jjjjj"> 
</select>
Postwar answered 9/8, 2013 at 19:7 Comment(2)
why you don't want to use options Caption?Postwar
you have to use some default text that has 'null' value., then the event wont get firedPostwar
E
7

I came across this post while looking for an answer to this question. I am not sure if this is still an issue but maybe the next person will benefit.

If I understand correctly, the issue is that the knockout data binding fire knockout events thus implementing undesired logic. I did some comparing of the actual JavaScript events and discovered that the events fired by knockout have different properties that events that are fired by user interaction.

Here is how I resolved this by checking the presence of these properties.

Instead of this:

self.addRequiredItem = function () {
    self.requiredItemSelection.push(new RequiredItemLine());
};

Try this:

self.addRequiredItem = function (ko_object, js_evt) {
    if(js_evt.cancelable === false) {
        self.requiredItemSelection.push(new RequiredItemLine());
    }
};

You can and should leverage the fact that you can pass knockout model and the JavaScript event into your events. The cancelable property does not seem to exist on the knockout dom events so I checked for it to ensure that the event was triggered by a user.

Enteron answered 26/6, 2013 at 20:35 Comment(0)
P
1

It will not fire if you set it with a default value.

Write something in optionsCaption. Use this syntax to add a caption:

<select data-bind="options: xxxx, 
                   optionsCaption:'select', 
                   optionsText: yyyy, 
                   value:  jjjjj"> 
</select>

or else you can use optionsCaption as shown below

<select data-bind="options: xxxx,
                optionsCaption: ' ',
               optionsText: yyyy, 
              value:  jjjjj"> 
</select>
Postwar answered 9/8, 2013 at 19:7 Comment(2)
why you don't want to use options Caption?Postwar
you have to use some default text that has 'null' value., then the event wont get firedPostwar

© 2022 - 2024 — McMap. All rights reserved.