1

In a Durandal app I have a dialog containing a view bound to a viewmodel.

The label elements for each of the input elements includes a warning glyph done with icon-warning-sign. The visibility of each glyph is controlled by data-binding like this:

<div class="form-group">
  <label for="email">
    Email <i class="icon-warning-sign orange" 
      data-bind="visible:Email.hasError, attr: { title:Email.validationMessage }"></i>
  </label>
  <input id="email" class="form-control" type="text" 
    data-bind="value: Email, valueUpdate: 'afterkeydown'" />
</div>

Email is an observable property of the view model. The hasError property is a sub-observable created by an extender. There are several of these, here's a sample. Only the validate implementation varies.

function prepForExtender(target) {
  if (target.hasError) return;
  target.hasError = ko.observable();
  target.validationMessage = ko.observable();
}

ko.extenders.required = function (target, overrideMessage) {

  prepForExtender(target);

  //define a function to do validation
  function validate(newValue) {
    target.hasError(!newValue);
    target.validationMessage(newValue ? "" : 
      overrideMessage || "This field is required");
  }

  //initial validation
  validate(target());

  //validate whenever the value changes
  target.subscribe(validate);

  //return the original observable
  return target;
};

Here's a sample use of an extender.

register.FirstName = ko.observable()
  .extend({ required: "First name is missing" });

It all works fine except for IE8. No titters about IE8 from the peanut gallery please, it's the client's SOE and that's all there is to it. In IE8 when the dialog opens the warning glyphs are not visible. If you edit an input's value then the glyph's visibility is correctly updated, so the bindings and the logic work ok.

How can I trigger evaluation when the dialog is first displayed?

More info: The glyphs don't become visible until there is a transition to hasError() == true. So if the page starts with hasError true for a given input then you have to cause hasError to return false and then true again in order to cause the glyph to become visible.

Peter Wone
  • 17,965
  • 12
  • 82
  • 134
  • Two thoughts come to mind: your initializaton of the observables, and perhaps the need to set zoom to 1.0 in your css. Also, are you creating computeds _just_ so you can hook each key press? If so, that's not necessary. –  Mar 24 '14 at 07:43
  • @Eric - I reviewed the code and discovered they're actually observables inside extenders. I've corrected the question. – Peter Wone Mar 24 '14 at 09:01
  • Take a look at #prepForExtender. Initialize each of the two observables with values: `target.hasError = ko.observable(false)` and `target.validationMessage = ko.observable('')`. The problem may lie there. Also, shouldn't it be `if (target.hasError())`? The non-dereferenced version refers to the observable itself, and will always be truthy. –  Mar 24 '14 at 17:16

0 Answers0