Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout fires change event when select list initializing

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 ?

like image 846
Arooran Avatar asked May 13 '13 12:05

Arooran


2 Answers

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.

like image 151
Jordan Papaleo Avatar answered Nov 04 '22 20:11

Jordan Papaleo


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>
like image 41
nikhil Avatar answered Nov 04 '22 22:11

nikhil