Reputation: 5393
I'm using Durandal, which in turn leverages off of Knockout.
I want to be able to Change validation lengths dynamically
The fiddle seems to be behaving slightly different than my "working" solution, but its still not doing what I'm wanting/expecting it to.
Viewmodel JS:
[Attempt 1]
define(function () {
var self = this;
self.userInfo = {
IdOrPassportNumber: ko.observable().extend({
required: true,
pattern: {
message: 'A message',
params: /some regex/
}
}),
IdType: ko.observable()
},
self.isIdValid = ko.validatedObservable({
IdOrPassportNumber: self.userInfo.IdOrPassportNumber
});
self.userInfo.IdOrPassportNumber.subscribe(function (value) {
if (isIdValid.isValid()) {
console.log('YOLO!');
}
});
self.userInfo.IdType.subscribe(function (value) {
console.log(value);
if (value === 'Passport') {
self.userInfo.IdOrPassportNumber.extend({ maxLength: 15 });
} else {
self.userInfo.IdOrPassportNumber.extend({ maxLength: 13 });
}
});
var viewModel = {
userInfo: self.userInfo
};
viewModel["errors"] = ko.validation.group(viewModel.userInfo);
viewModel["errors"].showAllMessages();
return viewModel;
});
What seems to be happening is that when i start typing i get the max & min validation of 13, but if i continue typing the validation changes to 15. I have tried another route of, setting the min & max length in the initial observable extend EG, just after the regex, and then setting the min and max length to use an observable, to no success.
[Attempt 2]
self.userInfo = {
IdOrPassportNumber: ko.observable().extend({
maxLength: self.maxLength(),
minlength: self.maxLength()
}),
IdType: ko.observable()
},
self.maxLength = ko.observable();
self.userInfo.IdType.subscribe(function (value) {
if (value === 'Passport') {
self.maxLength(15)
} else {
self.maxLength(3)
}
});
Upvotes: 10
Views: 7151
Reputation: 145960
You were so close :-)
You must provide the observable itself, not the unwrapped value. So just remove the ()
from maxLength()
- the validation library will automatically unwrap it for you.
self.userInfo = {
IdOrPassportNumber: ko.observable().extend({
maxLength: self.maxLength,
minlength: self.maxLength
}),
IdType: ko.observable()
},
Here's another example with dynamic regex patterns.
zipPostalPattern = ko.pureComputed(() => this.countryCode() === 'US' ? '^\\d{5}(?:[-\\s]\\d{4})?$' : '');
zipOrPostal: KnockoutObservable<string> = ko.observable('').extend(
{
required: true,
pattern: {
message: 'This is not a valid postcode for the country',
params: this.zipPostalPattern
}
});
or (if you don't want a message).
zipPostalPattern = ko.pureComputed(function() { return this.countryCode() === 'US' ? '^\\d{5}(?:[-\\s]\\d{4})?$' : ''});
zipOrPostal: KnockoutObservable<string> = ko.observable('').extend(
{
required: true,
pattern: self.zipPostalPattern
});
Important: If you don't want a custom message don't just remove the message
parameter and leave pattern = { params: this.zipPostalPattern }
because it won't work. If you don't have a message you must set the Regex/string directly for the pattern
parameter.
Or of course you can just define the computed observable in place (here it's ok to call countryCode()
as a function because that's how computed's work)
zipOrPostal: KnockoutObservable<string> = ko.observable('').extend(
{
required: true,
pattern: ko.pureComputed(function() {
return self.countryCode() === 'US' ? '^\\d{5}(?:[-\\s]\\d{4})?$' : ''
})
});
Upvotes: 5
Reputation: 37
consider this
self.iDNumber = ko.observable('').extend({
required: {
params: true,
message: 'ID Number is a required field.',
insertMessages: false
},
SouthAfricanIDNumber: {
message: 'Please enter a valid South African ID number.',
onlyIf: function() {
return self.identityType() === 'SAID';
}
}
});
where SouthAfricanIDNumber is a custom validation that uses regex.
Upvotes: 4
Reputation: 5393
Here is the solution that worked for me:
I made use of the custom validation feature, more specifically the single use custom validation as this wont be re-used elsewhere.
[Attempt 3]
self.userInfo = {
IdOrPassportNumber: ko.observable().extend({
required: true,
pattern: {
message: 'A message',
params: /some regex/
},
validation: {
validator: function (val) {
if (self.userInfo.IdType() === 'Id') {
return val.length === 13;
} else {
return val.length === 15;
}
},
message: function () {
if (self.userInfo.IdType() === 'Id') {
return 'Required: 13 characters';
} else {
return 'Required: 15 characters';
}
}
}
})
}
Upvotes: 6