Function in validator, not controller giving me an undefined at 'lowerCase()' - javascript

I have a form where I'm trying to ensure that case insensitivity is not a problem with an email validation. I have an angular validation called mustMatch that does just what it states, it makes sure that the emails match index for index. However I also need to make sure that case is not an issue. So I ended up creating a secondary function called matchCaseInsensitivity and ultimately that is where I am having a problem because I decided the best way to fix this would be by adding the tolowerCase() filter. When I did this, i was able to bypass my angular mustMatch error messages (which is good), but when I would hit a submit on the form, I would then run into a javascript problem in that 'tolowerCase()' is undefined.
I think that the reason why i'm getting this error is because I have these built in a validator file, not a controller. (not sure if that is anything)
My front end looks like this. Notice the 'match-case-insensitive' => true as my build for the solution
%input-md{ type: "email", "ng-model" => "vm.form.email_confirmation", required: true, 'must-match' => 'register_form["vm-form-email"]', 'match-case-insensitive' => true, 'ng-hide' => 'vm.form.validated_email', autocapitalize: 'off' }
Confirm email address
My mustMatch validation error message is
if attr.mustMatch then addValidation 'mustMatch', 'This field must match the previous value.'
The actual function that triggers the mustMatch error message, I also have it bundled with the 'match-case-insensitive' that I refer to in the front end. This also is in a validation file, not the controller. (for what that is worth....i dunno). (mind you, it is in coffeeScript)
getMatchValue = ->
match = matchGetter($scope)
if (angular.isObject(match) and match.hasOwnProperty('$viewValue'))
match = match.$viewValue
match
$scope.$watch getMatchValue, ->
ctrl.$$parseAndValidate()
return
ctrl.$validators.mustMatch = ->
match = getMatchValue()
if $attrs.matchCaseInsensitive
ctrl.$viewValue.toLowerCase() is match.toLowerCase()
else
ctrl.$viewValue is match
return
I continue to get this TypeError: Cannot read property 'toLowerCase' of undefined at r.$validators.mustMatch. I have been stuck on this for over 2 days, and truthfully have no idea how to solve it. I would really be grateful if someone could take a look and see what they can do.

From the error, it's clear that either ctrl.$viewValue or match (or both) are undefined. Not sure what you want the expected behavior to be in that situation, but here is one possible way you could do it (I'm going to write this in JavaScript):
match = getMatchValue()
if (!(match && ctrl.$viewValue)) {
return false
}
if ($attrs.matchCaseInsensitive) {
return ctrl.$viewValue.toLowerCase() === match.toLowerCase()
}
return ctrl.$viewValue === match

Related

How thoroughly should I check for possible errors in JavaScript?

I've difficulties to understand how far should I normally go with checking and validating data I operate in my code. I'm not even saying about user-input data here, I'm just saying about my own data, the data I know the structure of. For example, I might have some basic function like this:
let someData = [object];
someFunction(newData) {
let newSet = newData.frequency[0];
someData.dataset.chart.data[0].frequency = newSet;
}
Let's say I have someData variable that is used by a chart, and then I also have a function that simply updates the chart data with a new one. newData comes from my database (when user adjust filters and apply them) and someData is the default, initial data everyone sees. Now, my problem is... I foresee the following events:
Someone might change someData using Developers Console, so this variable will no longer hold an object, or won't have properties I address in my code, so it will lead to errors and break my logic entirely.
Someone might call someFunction directly (using console again) with very random data as argument, and this, again, will lead to errors.
Maybe newData received from DB will be somewhat wrong due to some errors on my side or anything, or maybe initial someData will fail initialising (cause it's initialised through a function as well and relies on third party .JS file that also might fail to load one day).
And I'm not even sure I've foreseen all possible events. So my code turns from what you saw above to something "tedious" (in my opinion) like this:
let someData = [object];
someFunction(newData) {
let newSet = typeof newData === "object" &&
newData.frequency ?
newData.frequency[0] : undefined;
let oldSet = typeof someData === "object" &&
someData.dataset &&
someData.dataset.chart &&
someData.dataset.chart.data &&
someData.dataset.chart.data[0] ?
someData.dataset.chart.data[0].frequency : undefined;
// Since using length on undefined will lead to an error, I've to check the type too
if (Array.isArray(newSet) && newSet.length === 5 && oldSet) {
oldSet = newSet;
} else {
throw Error("Dataset update has failed.");
}
}
And even this doesn't guarantee that the newSet of data is the data I expect to see, because maybe I was looking for [1,2,3,4,5] and user managed to insert ["a","b","c","d","e"] via his console and so on. It feels like I can refine this endlessly and it will never be bulletproof plus eventually it's starting to get complicated to understand my own code, that the only thing I wanted to do is to changed old data with the new data. At this point I'm feeling like I'm doing it all wrong. Coding takes way more time and I'm not even sure I'm doing it for good, but at the same time I can't feel the limit when to stop over-validating my code. Please advise.
I would just stick with user input validation. Out of that, it's their problem if they want to screw you things with developper tools. Anyway, those would only stay on their side.
What's important is the validation on your server. The client side input validation is just to make sure everything put by regular user is error free before processing. It also save useless send to server. The server must redo the validation and more because of those screwed people.

Validation without objects using Joi

good evening.
I'm having trouble while trying to validate a variable using Joi. I've read this page link
Joi usually validates object through schemas, however, the page I mentioned show that Joi also supports a more "direct" approach to validation. In my case, I'm trying just to validate a variable.
I'm trying the following:
const {error, value} = Joi.number().validate("SAMPLE TEXT");
It's not precisely what I'm trying to do (I'd change "SAMPLE TEXT" for a variable), but It's a good example to show my problem.
What I'd expect from this code is that an error is thrown (because validation should fail), meaning that ** error should not be null or undefined **, however, when trying:
console.log(`Error: ${error}`};
I get:
Error: undefined
Can anyone help me?
[]
Check your package is installed perfectly. I did not find any issue in your code. I have run it properly.
const Joi = require('#hapi/joi'); check this line also

Multiple errors per field in Mongoose validation

Has anyone workaround for getting all errors per field in Mongoose validation? Right now, when some field has an error, validation for that field stops, because of that, you need to resubmit form to see next error.
This behaviour might be fixed in future (https://github.com/Automattic/mongoose/issues/2612), but before that, I would love to see a workaround, which would let me to use validation method, for e.g.:
User.schema.path('hashed_password').validate(function (value) {
if ( ! something)
this.invalidate('password', 'Something is wrong with the password');
});
Note: Using validation method, I can bind error to any field, not just the one validated at the moment. Right now there is no plugin which would let me do that (I have tested mongoose-validator-all and mongoose-validate-all and those plugins are using different strategy).

How can I determine if all business rules are met in an entity form in Dynamics CRM 2013?

I have a form with two fields
e-mail
telephone
and a business rule that validates that at least one of them is set. There is a Silverlight application in the CRM that needs to know if the form can be saved or not. This should be done without saving it, thus invoking save() and catching exceptions is not an option. I can invoke Javascript from the Silverlight application, so a JS solution would be fine, too.
How can the SL application (or a JS function) know whether or not the form can be saved?
Happy coding
Arne
You say your business rule "validates" that one or the other is filled in. What action does it take if this is the case? I can think of several approaches to this, such as testing if one is NULL, make the other required.
You could just test to see if both are null, and show an error message against one or both. Displaying an error message from a rule will block saving of the record. Whether this will be enough to block your SL app from trying to save it as well, I'm not sure.
I solved the problem. In case this helps someone, I created business rules that make fields mandatory when some conditions are met. Then I created a JS function that checks if all fields that are mandatory are actually filled. This function did not work correctly for me. Here is the working version:
function IsAllMandatoryFieldsPopulated() {
var populated = true;
Xrm.Page.data.entity.attributes.forEach(function (attribute, index) {
if (attribute.getRequiredLevel() == 'required') {
if(attribute.getValue() === null) {
populated = false;
}
}
});
if (populated)
return '';
return 'Put your validation message here';
}
It did not work because of some hassles you get when you call this function form SL, but that is out of scope for this question. Hope this helps someone.

custom error display with parsley.js 2.x

I need to show a list of validation errors in a popup.
I've disabled UI modification with <form data-parsley-ui-enabled="false"... and subscribed to the "parsley:field:error" event, where I collect error information, and then on "parsley:form:validated" I display the popup, ofcourse only on the condition isValid() == false.
But I am having problems with getting the actual error message in the "parsley:field:error" handler. The handler gets a single parameter containing an object, which so far I inspected to have several properties:
$element - the actual jQuery field,
constraints - list of constraints
options.i18n - it has some raw error message strings which I can get iterating with an n variable like so: obj.options.i18n.<LANGUAGE_CODE>.[obj.constraints[n].name], but they ocasionally contain placeholders (%s) and therefore are not suitable for display to the end
user; and sometimes there's an array instead of a single string, which defeats the idea completely;
The question is, how do I get the actual error message which would got displayed if I hadn't disabled the UI?
Solution
Use the following way to access a prioritized error message (i.e data-parsley-priority-enabled=true):
$.listen('parsley:field:error', function(parsleyField) {
// parsley field
console.log(parsleyField);
// which constraint has failed
console.log(parsleyField.validationResult[0].assert.name);
// the data-parsley-<constraint>-message
console.log(parsleyField.options[parsleyField.validationResult[0].assert.name+'Message']);
// the default constraint fail message
console.log(window.ParsleyValidator.getErrorMessage(parsleyField.validationResult[0].assert));
});
Short Explanation
You were almost there, the messages are stored in the options object itself, and the format for the message is like this: <constraint>Message, for example: requiredMessage.
Which is similar to the "data attribute to js variable conversion" convention like in jQuery, this has been mentioned in the docs: <parsleynamespace>-<constraint>-message becomes <constraint>Message.
Got this idea after seeing the annotated source for ui.js, check the _getErrorMessage function.
To access all the validation messages for a field on error (i.e data-parsley-priority-enabled=false), you can simply iterate through the
parsleyField.validationResult array:
for (i=0; i<parsleyField.validationResult.length; i++) {
console.log(parsleyField.options[parsleyField.validationResult[i].assert.name+'Message']);
}

Categories