I'm trying to use knockout.validation
on a number of parts of a form. Most of this all works fine and can use the built in message appender, but I've got 1 specific field where I need to add the message myself manually to the DOM.
I'm having a real problem getting it working though, because I simply can't get the text to display if there hasn't been a change to the field. I've mocked up a really small example to illustrate as close to the larger form as I can.
The behaviour I'm seeing:
submit
correctly runs the validation (adds a red border around the input) but it doesn't display the error message like it should do.Due to the fact I'm trying to introduce a required field - I can't guarantee that the field has ever been modified, so I need to ensure the first case works. Can anyone see what I'm doing wrong?
ko.validation.init({
registerExtenders: true,
messagesOnModified: true,
insertMessages: true,
decorateInputElement: true,
decorateElementOnModified: false,
errorElementClass: "is-invalid",
messageTemplate: "inline_error"
}, true);
const viewModel = {};
viewModel.submitted = ko.observable(false);
viewModel.clicked = () => { viewModel.submitted(true); };
const onlyIf = ko.computed(() => viewModel.submitted());
viewModel.user = {
password: ko.observable().extend({
required: {
message: `password is required.`,
onlyIf,
}
})
};
ko.applyBindings(viewModel);
.is-invalid {
border: thick solid red;
}
.text-danger {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout-validation/2.0.3/knockout.validation.min.js"></script>
<div id="domTest">
<button type="button" data-bind="click: clicked">Submit</button>
<input type="password" class="form-control" id="password" placeholder="Password" data-bind="validationOptions:{ insertMessages: false }, textInput: user.password">
<div class="text-danger error-message" data-bind="validationMessage: user.password" />
</div>
In this Github issue, validationMessage does not run on initial binding, stevegreatrex say that you need to change messagesOnModified
to false:
messagesOnModified: false
And from the answer to this question Knockout Validation onlyif object no function and pattern validation
(by steve-greatrex) you need to change the onlyIf
computed:
viewModel.onlyIf = ko.computed(() => viewModel.submitted());
And then change the property onlyIf
in viewModel.user
to point to the computed viewModel.onlyIf
:
viewModel.user = {
password: ko.observable().extend({
required: {
message: `password is required.`,
onlyIf: viewModel.onlyIf(),
}
})
};
Hope this helps.
ko.validation.init({
registerExtenders: true,
//messagesOnModified: true,
messagesOnModified: false,
insertMessages: true,
decorateInputElement: true,
decorateElementOnModified: false,
errorElementClass: "is-invalid",
messageTemplate: "inline_error"
}, true);
const viewModel = {};
viewModel.submitted = ko.observable(false);
viewModel.clicked = () => { viewModel.submitted(true); };
viewModel.onlyIf = ko.computed(() => viewModel.submitted());
viewModel.user = {
password: ko.observable().extend({
required: {
message: `password is required.`,
onlyIf: viewModel.onlyIf(),
}
})
};
ko.applyBindings(viewModel);
.is-invalid {
border: thick solid red;
}
.text-danger {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout-validation/2.0.3/knockout.validation.min.js"></script>
<div id="domTest">
<button type="button" data-bind="click: clicked">Submit</button>
<input type="password" class="form-control" id="password" placeholder="Password" data-bind="validationOptions:{ insertMessages: false }, textInput: user.password">
<div class="text-danger error-message" data-bind="validationMessage: user.password" />
</div>