Custom validation in angularjs compare two dates - javascript

I have two fields hiring_date and expiry_date
I am using angular UI datepicker.
I want to validate the form if hiring date is greater than the expiry date
This is my code:
logic is okay but how can I set this to form error as false
<small ng-show="formStep1.expiry_date.$invalid &&
formStep1.expiry_date.$touched " class="errorMsg ">
Please enter valid date (YYYY-MM-DD).</small>
<small
ng-show="formStep1.expiry_date.$modelValue < formStep1.hiring_date.$modelValue"
class="errorMsg ">
Expiry Date should not be a older than Target Hiring Date.</small>
i am getting true and false in this based on two input dates
formStep1.expiry_date.$modelValue < formStep1.hiring_date.$modelValue
Is it possible to do validation from view side..?
The message is displaying fine but i want the field expiry_date should be like required.
I have tried something like this but not working:
<input datepicker-options="dateOptions"
type="text"
class="form-control"
ng-model="expiry_date"
is-open="config2.opened"
uib-datepicker-popup="yyyy-MM-dd"
close-text="Close"
name="expiry_date"
show-button-bar="false"
ng-required="formStep1.expiry_date.$modelValue < formStep1.hiring_date.$modelValue ? 'true': 'false'" />

I would suggest using momentJs for any kind of date manipulation. Tom Scott could explain you why here. Anyway, for your particular case, there is a moment-angular library that could be use as such :
/* controller declaration */.('$scope', 'moment', function($scope, moment) {
$scope.isDateBefore = function(firstDate, secondDate) {
return moment(firstDate).isBefore(secondeDate);
}
})
<small
ng-show="isDateBefore(formStep1.expiry_date.$modelValue, formStep1.hiring_date.$modelValue)"
class="errorMsg ">
You can learn more about the isBefore function on the official momentjs doc

<span ng-if="formStep1.expiry_date.$modelValue < formStep1.hiring_date.$modelValue ? invalidExp(): ''" ></span>
$scope.invalidExp = function () {
$scope.formStep1.expiry_date.$valid = false;
}
this one worked. any better solution then this..?

Related

Creating a reusable method attach to input field for multiple components in Angular

I am beginner in angular and started working on angular 12 project. I am working on reactive forms where I am adding on Blur method to add class to my input field on some error conditions to give some styling to input fields.
I am able to do that but now I have 12-15 components with forms. I want to utilize the same functionality on all the components. Is there a way I can do this without repeating the code in ts file for onblur method. Below is my code.
<form [formGroup]="changePasswordForm" (ngSubmit)="submitForm()">
<div class="form-group" [ngClass]="f.oldPassword.invalid && ((f.oldPassword.dirty || f.oldPassword.touched))?'has-error':''">
<label>Old Password<span class="error-red">*</span></label>
<input type="password" class="form-control input-type2" formControlName="oldPassword" (blur)="onBlur($event)">
<div class="error error-msg">
<div *ngIf="f.oldPassword.errors?.required">
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i> Old password is required.
</div>
</div>
</div>
</form>
Component.ts
onBlur(e: any) {
if (e.target.className && e.target.className.indexOf('ng-invalid') > 0) {
e.target.className = e.target.className.replace('has-success', '');
} else {
e.target.className = e.target.className + ' has-success';
}
}
I am writing the same piece of code in all the form components to get my work done. I know one way to deal above is create service and write it down over there. But I did some research and found that we can create directives for such things. But I am not sure how to do it. Any help will be appreciated. Thanks.
You can use a directive on the input
#Directive({ selector: "[errorStyling]" })
export class ErrorStylingDirective {
constructor(
private elem:ElementRef
) { }
#HostListener("blur")
onBlur() {
// do something here
}
}
You could also use #HostBinding('class.xxx') approach to set the updated classes

How to implement validation/restriction in react-datepicker

I am trying to implement restriction or validation in a react-datepicker component. I am using redux-form for validation and normalization(to implement restriction)
https://redux-form.com/6.0.0-rc.1/examples/normalizing/
Question : I have observed that neither normalizing function nor validation functions of redux-form is called when we try to enter something in the field
although this value is not submitted when we submit the form but i need to show some validation error or restrict user from typing invalid characters.
I made a wrapper for the date picker component and used it in my form through redux field
my date picker component :-
return (
<div className={"render-date-picker "}>
<div className="input-error-wrapper">
{(input.value) ? <label> {placeholder} </label> : ''}
<DatePicker className="input form-flow" {...input}
placeholderText={placeholder}
selected={input.value ? moment(input.value) : null}
maxDate={maxDate || null}
minDate={minDate || null}
dateFormat={isTimePicker ? "LLL" : "DD/MM/YYYY"}
showYearDropdown
showMonthDropdown
disabledKeyboardNavigation
/>
{touched && error && <span className="error-msg">{t(error)}</span>}
<span className="bar" style={{ 'display': this.state.is_focus ? 'block' : 'none' }} ></span>
</div>
</div>
);
redux form field :-
<Field
name="date_of_birth"
type="text"
className="input form-flow extra-padding-datepicker"
component={RenderDatePicker}
maxDate={moment().subtract(18, "years")}
validate={[required, dateOfBirth]}
normalize={isValidDateFormat}
placeholder={t("DOB (DD/MM/YYYY)")}
/>
my normalizing function:-
export const isValidDateFormat = (value, previousValue) => {
if (value == null || !value.isValid()) {
return previousValue;
}
return value;
}
react-datepicker provides onChangeRaw property to get raw (typed) value inside the datePicker. In order to restrict or validate the datepicker input field we need the raw value which is not available on onChange event of the datepicker component.
for instance if we observe the onChange event :-
It returns a moment object.
In order to get raw value we use onChangeRaw
The raw value is obtained simply from e.target.value.
In my case I simply restrict the user from typing anything in the datepicker input field by a simple function:-
handleChangeRaw = (date) => {
let s=document.getElementById(date_picker_id)
s.value =moment(this.props.input.value).format("DD/MM/YYYY");
}
My datepicker component :-
<DatePicker
.....
disabledKeyboardNavigation
onChangeRaw={(e)=>this.handleChangeRaw(e)}
id={date_picker_id}
.....
/>
This solved my problem. Hope it is useful :)

How to close calendar popup after clicking on date

How can I hide the calendar after a date is selected? I am using Date-time-picker by DanyelYKPan.
Is there a specific function that I can use? My code below
<div class="col-3">
<div class="form-group calenderForm calenderForm1">
<label for="templateName">REPAIR DATE (FROM)</label>
<owl-date-time name="repairDateFrom"
[(ngModel)]="repairDateFrom"
[max]="max"
[type]="'calendar'"
[dateFormat]="'YYYY-MM-DD'"
[placeHolder]="'YYYY-MM-DD'"
></owl-date-time>
<div class="error-message-block"></div>
<input type="hidden" name="repairDateFrom" id = "repairDateFrom" value="
{{repairDateFrom | date: 'yyyy-MM-dd'}}" (click)="closeDatePopUp()"/>
</div>
</div>
From top of the code through picker plugin component call will goes to below function.
DateTimePickerComponent.prototype.updateFormattedValue = function () {
var formattedValue = '';
if (this.value) {
var d = new Date();
if (this.isSingleSelection()) {
this.value = this.value.setHours(d.getHours(), d.getMinutes());
formattedValue = date_fns_1.format(this.value, this.dateFormat,
{ locale: this.locale.dateFns });
$('.owl-calendar-wrapper').on('click',function(){
$('.owl-dateTime-dialog').hide();
});
}}}
I tried with above code it will works only one time after clicking on date field second time date popup will not come.
Please help me to solve this problem.
If I were you I would use the mechanism of Parent call of #ViewChild described in the angular Component Interaction page.
1 - import the DateTimePickerComponent
import { DateTimePickerComponent } from "ng-pick-datetime/picker.component"
2- Refer it to ViewChild and assign a variable name:
#ViewChild(DateTimePickerComponent) picker: DateTimePickerComponent;
3- Now you can access all non private attribute/method described here: https://github.com/DanielYKPan/date-time-picker/blob/master/src/picker.component.ts by this.picker
For hiding the calendar you can set the dialogVisible to false:
this.picker.dialogVisible = false
Now time to detect the click event in our calendar. The simplest way is to use (ngModelChange) event.
<owl-date-time
[(ngModel)]="repairDateFrom" name="repairDateFrom"
(ngModelChange)="onDateChange()"
[type]="'calendar'"
[dateFormat]="'YYYY-MM-DD'"
></owl-date-time>
And in our component :
onDateChange() {
this.picker.dialogVisible = false;
}

daterangepicker not getting triggered

I am implementing daterange picker in my page. But it is not working. Could somebody please point out what am I doing wrong or What is that I am missing.
CSHTML:
<div class="has-feedback" >
<input type="text" id="txtDateRange"
class="form-control input-md" name="RangeDates"
placeholder="Select Range"
ng-model="Model.RageDates">
<span class="form-control-feedback"><i class="glyphicon glyphicon-calendar fa fa-calendar"></i></span>
<span style="color: #a94442" >
<label class="control-label" class="has-error" ng-show="RangeDates.$invalid">Required.</label>
</span>
</div>
js :
DashBoardModule.controller('DashBoardController', ['$scope','$filter', 'DashBoardModuleService', function ($scope,$filter, DashBoardModuleService) {
$('#txtDateRange').on('apply.daterangepicker', function (ev, picker) {
$scope.isRefreshing = true;
$scope.Model.introductoryPeriodEnd = $filter('date')(new Date(picker.endDate), dateFormat);
$scope.Model.introductoryPeriodStart = $filter('date')(new Date(picker.startDate), dateFormat);
$scope.Model.typeAvailability = picker.chosenLabel === "Custom Range" ? "Custom" : picker.chosenLabel;
$scope.$apply();
});
angular.element(document).ready(function () {
var dateConfiguration = new Date();
$('#txtDateRange').daterangepicker({
ranges: {
'Next Week': [new Date(), dateConfiguration.setDate(dateConfiguration.getDate() + 6)],
'Next 2 Weeks': [new Date(), dateConfiguration.setDate(dateConfiguration.getDate() + 8)]
},
format: dateFormat,
autoApply: true
});
});
}]);
_Layout :
<!-- Range Date Picker -->
<link href="~/Scripts/Controls/DateRangePicker/daterangepicker.css" rel="stylesheet" />
<script src="~/Scripts/Controls/DateRangePicker/daterangepicker.js"></script>
First, I'm not answering your question. Because I prefer advice you: AVOID IT.
What you are doing is not the Angular Way. You are working in the jQuery Way. So, will be harder to you to use Angular and Libs. So, you have 2 choices: use AngularJS or use jQuery.
Why you are not doing in Angular way:
0 - With Angular you shouldn't use jQuery to select elements. (you are using with the $('#txtDateRange').on('apply.daterangepicker', and angular.element(document).ready and $('#txtDateRange').daterangepicker
Take care of this. Or Angular will be harder and not elegant.
If you prefer to use angular, you can use an ANGULAR Date Picker, Please check this: http://mgcrea.github.io/angular-strap/#/datepickers
I hope it can help you!

Setting options to datepicker in angular-ui bootstrap

I'm trying to use datepicker component from angular-ui bootstrap lib as descibed here: http://angular-ui.github.io/bootstrap/
And I try to set options for the popup picker and accoriding to the documentation I should pass options for datepicker as JSON using the datepicker-options attribute.
In my view I have:
<div class="row">
<div class="col-md-6">
<p class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}" ng-model="dt" is-open="opened" min="minDate" max="'2015-06-22'" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
</div>
And in my controller I have:
$scope.dateOptions = {'show-button-bar': 'false', 'close-text':'SomeText'};
$scope.today = function() {
$scope.dt = new Date();
};
$scope.today();
$scope.showWeeks = false;
$scope.clear = function () {
$scope.dt = null;
};
$scope.toggleMin = function() {
$scope.minDate = ( $scope.minDate ) ? null : new Date();
};
$scope.toggleMin();
$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened = true;
};
$scope.dateOptions = {
'year-format': "'yy'",
'starting-day': 1
};
$scope.format = 'dd/MM/yyyy'
As you can see at the beginning I try to set the options:
$scope.dateOptions = {'show-button-bar': 'false', 'close-text':'SomeText'};
however, it doesn't seem to work, the datepicker does not change.
Any ideas what I'm doing wrong?
I found the solution to this, I put the options as attributes, e.g.:
<input type="text" class="form-control" datepicker-popup="{{format}}" ng-model="dt" is-open="opened" min="minDate" max="'2014-12-31'" datepickerOptions="dateOptions" ng-required="true" show-button-bar="false"/>
so I put show-button-bar as the attribute and not as a part of object passed to datepickerOptions.
You are using dash-cased option names. These dash-cased names are only required when using them as single attributes on an element. i.e.
<input type="text" datepicker-popup="{{format}}" starting-day="1" ng-model="dt" >
However datepicker-options expects named options in json with camelCased format as following:
datepicker-options="{startingDay: 1, yearFormat: 'yy'}"
<input type="text" datepicker-popup="{{format}}"
datepicker-options="{startingDay: 1, yearFormat: 'yy'}" ng-model="dt" >
or
$scope.options = {
'startingDay': 1,
'yearFormat': 'yy'
}
<input type="text" datepicker-popup="{{format}}"
datepicker-options="{{options}}" ng-
The attribute starting-day="1" should also work on the datepicker input, as told at https://angular-ui.github.io/bootstrap/#/datepicker, but I can't seem to get that working (using version 0.12.1)
I know this an old question but thought I'd point out where you were probably having trouble.
In your controller you are assigning to $scope.dateOptions twice and therefore overwriting your first assignment.
So your initial assignment of:
$scope.dateOptions = {'show-button-bar': 'false', 'close-text':'SomeText'};
Is overwritten when you do this towards the end:
$scope.dateOptions = {
'year-format': "'yy'",
'starting-day': 1
};
According to datePicker documentation, popup setting can be globally configured through the datepickerPopupConfig, so you have to add it into you controller.
yourApp.controller('YourController', function ($scope, datepickerPopupConfig) {
datepickerPopupConfig.showButtonBar = true;
datepickerPopupConfig.closeText = 'I am done';
datepickerPopupConfig.clearText = 'Wipe it out';
}
Setting closeText doesn't work for some reason. I don't know why.
Example on Plunker for playing.
datepicker-options was introduced in version 0.11 so make sure you are using angular-ui-bootstrap version 0.11 or higher
Looks like your dateOptions object keys are not camelCased. Try this:
$scope.dateOptions = {
'showButtonBar': 'false',
'closeText':'SomeText'
};
Html attributes should be dash-cased, like show-button-bar, or close-text, etc.
Notice the difference between the datepicker-options html attribute and the datepickerOptions javascript object.
Just provide close-text, current-text and clear-text attributes in the input :)
<input type="text" uib-datepicker-popup ng-model="dt" is-open="popup2.isopen" datepicker-options="dateOptions" ng-required="true" close-text="your close text here" current-text="Your current text here (today for example)" clear-text="Your clear-text here"/>
The site is pretty lite on examples. For me, with version 1.1.1, I passed in the config object as an attrib:
datepicker-options="datepickerOptions"
And in the controller, was able to set some options:
$scope.datepickerOptions = {
formatYear: 'yy',
startingDay: 0,
showWeeks: false
};
But 'showButtonBar' doesn't cooperate, so looking through the code I saw 'uibDatepickerPopupConfig'. I pass that in and and set it separately and it works:
.controller('DatepickerCtrl', function ($scope, uibDatepickerPopupConfig){
uibDatepickerPopupConfig.showButtonBar = false;
With 'datepickerPopupConfig' I get the provider error:
Unknown provider: datepickerPopupConfigProvider <- datepickerPopupConfig

Categories

Resources