0
votes

I had run into deep troubles with knockout when running on IE9 with IE8 compatibility mode. Here's the issue:

I have an array of dynamically generated textboxes, and a change event is bound to these elements. When the change event is there, in IE8 compatibility mode, I need to press tab twice to move away from the control. This doesn't happen in Firefox, nor when there's no event bound.

I'm not sure whether it's an issue with my event so I'm posting the code here:

  <tbody data-bind="foreach: DailyItemList">
                            <tr>
                                <td>
                                 <span  data-bind="text:Day"></span>

                                </td>
                                <td><input id="Text2" data-bind="value: Required"/></td>
                                <td><input id="Text3" data-bind="value: Setup, event:{change: ValidateSetup}"/></td>
                                <td><input id="Text4" data-bind="value: Close, event:{change: ValidateClose}"/></td>
  </tr>
  </tbody>

Here's the view model with the change functions:

var DailyItem = function (data) {
this.Day = ko.observable(data.DayOfWeek);
this.Required = ko.observable(data.Required);
this.Setup = ko.observable(data.SetupTime);
this.Close = ko.observable(data.CloseTime);
this.ValidateSetup = function () {
    if (this.Setup() > 30) {
        alert('Invalid SetupTime');
    }
}
this.ValidateClose = function () {
    if (this.Close() > 30) {
         alert('Invalid SetupTime');
    }
}
}

function ViewModel(items) {
   this.DailyItemList = ko.observableArray([]);
   records = $.map(items, function (data) { return new DailyItem(data) });
   this.DailyItemList(records);
}
1
don't do a change event. make ValidateSetup a computed accessing the value of the input. remove the event: {change and you are good to go. - Sujesh Arukil
HI, thanks for your response, but I need to do several things inside the function - what I have shown is just an example. I need to update several other observables inside the function. - devC
You can still do it inside the computed. But if you don't want a computed, subscribe to the underlying observable and do what you need to do. - Sujesh Arukil

1 Answers

2
votes

If you want to work around the IE8 compatibility, then you can return true from your Validate functions.

this.ValidateSetup = function () {
    if (this.Setup() > 30) {
        alert('Invalid SetupTime');
    }

    return true;
}

Here is a sample: http://jsfiddle.net/rniemeyer/FfNqv/ (jsFiddle has some issues itself in IE8 mode, so you can run http://jsfiddle.net/rniemeyer/FfNqv/show/)

A better approach though would likely be to use a manual subscription. This is a good option for executing code whenever a single observable changes. The same could be done in a computed as well, which allows you to depend on multiple observables.

With a manual subscription you would do:

<input id="Text3" data-bind="value: Setup"/>

In your view model, you would something like:

this.Close = ko.observable(data.CloseTime);
this.Close.subscribe(function(newValue) {
    if (newValue > 30) {
        alert('Invalid SetupTime');
    }

    //set other observables, or do whatever you like. "this" will be the this object.

}, this);