Codeigniter validation--how to limit numerical value? - validation

I simply need to add a validation class that limits a numerical entry from being greater than 24.
Is this possible with CI's default validation classes or will I have to write a custom validation class?

You can use validation rule "greater_than[24]"
like for Example
$this->form_validation->set_rules('your_number_field', 'Your Number', 'numeric|required|greater_than[24]');

There's no maximum or minimum comparison function in the Form Validation Rule Reference, so you can just write your own validation function.
It's pretty straightforward. Something like this should work:
function maximumCheck($num)
{
if ($num > 24)
{
$this->form_validation->set_message(
'your_number_field',
'The %s field must be less than 24'
);
return FALSE;
}
else
{
return TRUE;
}
}
$this->form_validation->set_rules(
'your_number_field', 'Your Number', 'callback_maximumCheck'
);

Sure you can, just make your own validation function and add it as a callback to validation rule. See http://codeigniter.com/user_guide/libraries/form_validation.html#callbacks
Hence, you will have
...
$this->form_validation->set_rules('mynumber', 'This field', 'callback_numcheck');
....
function numcheck($in) {
if (intval($in) > 24) {
$this->form_validation->set_message('numcheck', 'Larger than 24');
return FALSE;
} else {
return TRUE;
}
}

Related

Angular 2, custom validation messages with parameters

I'm just starting with JS/Typescript and Angular 2 and I'm struggling with the following.
export function MinImageDimensionsValidator(minWidth: number, minHeight: number): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
// it's an image control where a user uploads an image.
// the whole image related code has been removed for better readability.
//Just assume that 'actualWidth' holds the actual width of the image
if(actualWidth < minWidth) {
return { valid: false };
}
return null;
};
}
this is just a very basic example of a validator factory.
All the examples I found just wrote the validation messages/errors directly in the template (I'm using template forms)
Is it possible to "tie" the validation messages to the validator itself and use parameters with it?
like:
'Min width has to be 100. you supplied ' + actualWidth
this would be returned from the validator itself.
or is there another way (apart from storing everything in variables somewhere) ?
Yes, you can return any object from the validator. In your case it could be something like
return { minImageDimensions: { min: minWidth, value: actualWidth } }
When displaying field validation errors, you can do this:
<input #myField="ngModel" [(ngModel)]="...">
<span *ngIf="myField.errors.minImageDimensions">
Min width has to be {{ myField.errors.minImageDimensions.min }}.
You supplied {{ myField.errors.minImageDimensions.value }}.
</span>
Or even better use some localization and messages with parameters. You can make a component that will take a field object and display all kinds of error messages you use in your application according to the myField.errors object.
ValidatorFn should return a {[k:string]:any}, so it's as easy as this :
export function MinImageDimensionsValidator(minWidth: number, minHeight: number): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
if (actualWidth < minWidth) {
return {
myValidator: `Min width has to be ${minWidth}. you supplied ${actualWidth}`
};
}
return null;
};
}
then you can access this error like myFormControl.errors.myValidator.

Require a field only if a checkbox is checked CakePHP 2 Validation

Heres the problem
I want to require a field (litters_per_year) only if another field that is a checkbox is checked. When I do this, cake is trying to force me to put a value into the field and I don't know why. I have tried setting required & allowEmpty to false & true respectively, but then my custom rule does not run.
Heres the code
NOTE: The details of the following code aren't that important - they are here to provide a scenario.
I have the following code in my VIEW which works fine:
echo $this->Form->input('litters_per_year', array(
'label' => 'Litters per year (average)'
));
I have the following code in my MODEL's public $validate:
'litters_per_year' => array(
'isNeeded' => array(
'rule' => array('isNeeded', 'litters_per_year'),
'message' => 'Please enter the litters per year average'
)
)
which is calling the custom validation method
public function isNeeded($field) {
// Check if a checkbox is checked right here
// Assume it is not... return false
return false;
}
It returns false for simplicity to solve this issue.
Let's assume that the checkbox field is named 'the_checkbox'.
At the moment your field should always fail validation, since you return false from isNeeded.
To make it work as you expect, do something like this:
(Note: replace 'ModelName' with your model name)
public function isNeeded($field) {
if ($this->data['ModelName']['the_checkbox']) {
// Checkbox is checked, so we have to require litters per year
if (empty($field)) {
// They have checked the box but have NOT entered litters_per_year
// so we have a problem. NOT VALID!
return false;
} else {
// They have checked the box, and entered a litters_per_year
// value, so all good! Everything is valid!
return true;
}
} else {
// Checkbox is not checked, so we don't care what
// the field contains - it is always valid.
return true;
}
}
Or, without the needless verbosity, this should work:
public function isNeeded($field) {
if ($this->data['ModelName']['the_checkbox']) {
return $field;
} else {
return true;
}
}
In this example, if the checkbox is checked, validation will pass if $field is truthy, and fail if it is falsey.

AngularJS + custom validations

I have some doubts about AngularJS + Custom Validations, from what I have read and checked by myself:
AngularJS provides great helpers for simple field validation (ng-require, ...).
The best way to implement a single field custom validation is via directive (not polluting the controller).
My doubts come when we have custom business validations that impact on more than one filed. Let's check the following simple scenario:
We are editing a flight arrival status, fields: Status (landed / scheduled / delayed), comments (additional info abot the flight status).
The business validations that I want to apply is: comments fields is required only if status fields value is "Delayed".
The way I have implemented it:
Define a directive to take care of Status + Comments field changes (status via $watch).
This directive delegates the business validation into a service
The benefits I think this approach is giving to me are:
My business service validation gets isolated.
I could easily add unit testing to that business validation.
I could reuse it and it doesn't depend on UI elements.
I have compiled this sample in a JSFiddle (JSFiddle validation sample).
JS:
function MyCtrl($scope) {
$scope.arrival = {
"id": 1,
"originAirport": "Malaga (AGP)",
"flightNumber": "Iberia 132",
"dueAt": "2013-05-26T12:10:10",
"status": 2,
"info": "test"
}
}
myApp.directive('validateinfofield', ['formArrivalValidation', function (formArrivalValidation) {
return {
require: "ngModel",
link: function(scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function(viewValue){
// Empty? Let's check status
//if (!viewValue.length && scope.arrival.status == 3) {
if(formArrivalValidation.validateInfoField(scope.arrival.status, viewValue)) {
ctrl.$setValidity('validInfo', true);
} else {
ctrl.$setValidity('validInfo', false);
}
});
// Let's add a watch to arrival.status if the values change we need to
// reevaluate, if comments is empty and status is delayes display error
scope.$watch('arrival.status', function (newValue, oldValue) {
if (formArrivalValidation.validateInfoField(newValue, scope.editArrivalForm.txInfo.$viewValue)) {
ctrl.$setValidity('validInfo', true);
} else {
ctrl.$setValidity('validInfo', false);
}
});
}
};
}]);
// Validation Service, limited to our "business language"
myApp.factory('formArrivalValidation',
function () {
return {
validateInfoField: function (status, infoField) {
var isOk = true;
if (status == 3) {
if (infoField == undefined) {
isOk = false;
} else {
if (!infoField.length)
isOk = false;
}
}
return isOk;
},
};
});
Is this a good approach to follow? Is there better and simpler way to achieve this?
Regarding this part - "The business validations that I want to apply is: comments fields is required only if status fields value is "Delayed".
for comment field set ng-required="flight.status == 'DELAYED'"
Coming back to this question... one valid approach could be to write a directive that accepts as parameter a second value (e.g. comments is empty)

Dynamically switching the error message on validation?

With the new validator object - is it possible to replace the validation error inside the validation rule triggered? to not only return the static error message but maybe some dynamically genereted one?
public function validateLength($data) {
...
$length = mb_strlen($data['name']);
$this->validator()->getField('name')->setRule('validateLength', array('message' => $length . 'chars'));
...
}
does not work, of course (too late I guess)
I want to actually return the lenght of the string (you used 111 chars from 100 allowed) for example - but for this I would need to be able to replace the message from inside the (custom) validation method
$this->validate['name']['validateLength']['message'] = $length . 'chars';
also never worked so far. it would always return the previous (static) error message from the $validate array
public function customValidator($data) {
....
if ($validates) {
return true;
} else {
return 'my new error message';
}
}
The following snippet should do the trick:
public function validateLength($data) {
...
$length = mb_strlen($data['name']);
$this->validator()->getField('name')->getRule('validateLength')->message = $length . 'chars';
...
}

Use another rule if callback returns false

I'm using the following rule for my input:
callback_validate_host
I need to make the following condition:
if callback_validate_host is FALSE afterwards it should use the valid_ip validation rule.
So if validation of both: callback_validate_host and valid_ip on one input if FALSE then is should throw an error message.
How can I do that?
How about using your existing validate_host() method in conjunction with the Input class' $this->input->valid_ip($ip) method to create a single callback? Something like this:
public function your_custom_rule($input) {
if (! $this->validate_host($input) && ! $this->input->valid_ip($input)) {
// validate_host() returned FALSE *and* it's not a valid IP
$this->form_validation->set_message('your_custom_rule', 'Error msg');
return FALSE;
} else {
return TRUE;
}
}

Resources