简体   繁体   中英

Element not updating error state when value changed via javascript

I have a page with some knockout in it that I am trying to implement validation in. I have an input that I allow the user to change with a drop down like this:

<div class="col-md-6 form-group has-feedback" data-bind="css: { 'has-error': Term.hasError }">
    <label for="ddlTerm" class="col-form-label" style="padding: 0;">Term</label>
    <div class="input-group input-group-sm">
        <input type="text" data-bind="textInput: Term" class="form-control input-sm" id="tbTerm" />
        <div class="input-group-btn">
            <button type="button" class="btn btn-warning dropdown-toggle" data-toggle="dropdown">Select <span class="caret"></span></button>
            <ul class="dropdown-menu pull-right">
                <li><a href="javascript:set_Term(12)">12 Months</a></li>
                <li><a href="javascript:set_Term(24)">24 Months</a></li>
                <li><a href="javascript:set_Term(36)">36 Months</a></li>
                <li><a href="javascript:set_Term(48)">48 Months</a></li>
                <li><a href="javascript:set_Term(60)">60 Months</a></li>
                <li><a href="javascript:set_Term(72)">72 Months</a></li>
                <li><a href="javascript:set_Term(84)">84 Months</a></li>
            </ul>
        </div>
    </div>
    <span data-bind='visible: Term.hasError, text: Term.validationMessage' class="help-block"></span>
</div>

And the JavaScript function:

function set_Term(months) {
    var termInput = document.getElementById("tbTerm");
    termInput.value = months;           
};

The value is tied to:

self.Term = ko.observable('').extend({ required: 'Term is required' });

The observable is updated when the value changes, but the error state remains the same and the input stays red and the feedback remains visible. Is there a way to force the input to realize that it's value has been changed and it should clear the error?

I've tried to give the element focus() , but that doesn't work.

The only thing that I have found is to give the containing div and the validation message ids and then do this in the JS function:

  $('#tbTermDiv').removeClass('has-error');
  $('#tbTermNote').addClass('hidden');

Which visually does the trick - the error message goes away and the text box loses the red, but if the user then empties the box again, the red comes back but the message stays hidden... so not the best solution.

I'd be happy with any kind of solution: knockout, jQuery, pure JS.

Edit: I have noticed that this does not update the observable, so when I change the input via the value property it does not update the observable.

The extender works the same way knockout in general works. It's only aware of changes that are done to observables on a view-model. Updating the value of a control on the UI using jquery won't update the underlying view-model so any dependent knockout code doesn't know to update.

You can change your set_term function to be a function on the view-model, and have it update the underlying observable instead of the control. Then use a data-bind to call the function instead of raw js.

  self.set_Term = function(months) {
      self.Term(months);
  };

...

  <li><a data-bind="click: function(){set_Term(84)}">84 Months</a></li>

Here's an updated example: https://jsfiddle.net/jlspake/8ob0gj6q/3/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM