Liferay <liferay-ui:input-date> control - javascript

Hy all,
I'm new to Liferay and I making some porting from jsp to Liferay portal.
If I have a portlet jsp with two date in it like:
FromDate
ToDate
and use two different liferay-ui:input-date one for each date field like:
...
<%-- From DATE --%>
<tr>
<td>
From date :
</td>
<td>
<liferay-ui:input-date
dayParam='<%= "strDataRegDa" + "Day" %>'
dayValue="<%=Integer.parseInt(strDataRegDa.substring(0,2))%>"
dayNullable="<%= false %>"
monthParam='<%= "strDataRegDa" + "Month" %>'
monthValue="<%=(Integer.parseInt(strDataRegDa.substring(3,5))) -1 %>"
monthNullable="<%= false %>"
yearParam='<%= "strDataRegDa" + "Year" %>'
yearValue="<%=Integer.parseInt(strDataRegDa.substring(6))%>"
yearNullable="<%= false %>"
yearRangeStart="<%= 1980 %>"
yearRangeEnd="<%= 2050 %>"
firstDayOfWeek="<%= Calendar.MONDAY - 1 %>"
imageInputId='<%= "ceremonyDate"%>'
disabled="false" >
</liferay-ui:input-date>
</td>
</tr>
<%-- To DATE --%>
<tr>
<td>
To date :
</td>
<td>
<liferay-ui:input-date
dayParam='<%= "strDataRegA" + "Day" %>'
dayValue="<%=Integer.parseInt(strDataRegA.substring(0,2))%>"
dayNullable="<%= false %>"
monthParam='<%= "strDataRegDa" + "Month" %>'
monthValue="<%=(Integer.parseInt(strDataRegA.substring(3,5))) -1 %>"
monthNullable="<%= false %>"
yearParam='<%= "strDataRegDa" + "Year" %>'
yearValue="<%=Integer.parseInt(strDataRegA.substring(6))%>"
yearNullable="<%= false %>"
yearRangeStart="<%= 1980 %>"
yearRangeEnd="<%= 2050 %>"
firstDayOfWeek="<%= Calendar.MONDAY - 1 %>"
imageInputId='<%= "ceremonyDate"%>'
disabled="false" >
</liferay-ui:input-date>
</td>
</tr>
....
is there a way to control that ToDare is >= FromDate ?
With pure jsp I can do that via javascript.
But with Liferay how can achieve that ?

In our project I used manual Validation for the two dates in my Portlet Class for the dates. I had also searched but couldn't get anything which liferay provides. Through javascript don't know if Alloy UI provides something.
So in my humble opinion liferay does not provide any functionality for validating the two dates (atleast as of now), as can be seen from some out-of-box liferay portlets which does not have this validation like for example the Announcements-portlet with display-date and expiry-date.

Maybe you need something like custom validator.
Try this in your jsp:
<liferay-ui:input-date name="fromDate"></liferay-ui:input-date>
<liferay-ui:input-date name="toDate">
<aui:validator name="custom" errorMessage="your custom validation msg">
function(val, fieldNode, ruleValue)
{
// No error when toDate is blank
if(val == ""){
return true;
}
var fromDate;
var toDate;
var result=false;
var fromDateObj = document.getElementById("<portlet:namespace />fromDate");
if(fromDateObj) {
fromDate = new Date(fromDateObj.value);
}else{
result = false;
}
toDate = new Date(val);
if(fromDate && toDate){
result = (toDate.getTime() > fromDate.getTime());
}else{
result = false;
}
return result;
}
</aui:validator>
</liferay-ui:input-date>
Hope this helps you.
Thanks.

My answer is based on AGis answer. If you use e.g. the German language settings, the liferay-ui:input-date formats its value into DD/MM/YYYY instead of MM/DD/YYYY (I still don't know how to change the format of input-date..). That means fromDate = new Date(fromDateObj.value) does not work. So I do a workaround, access day, month and year directly and compare the values manually. An advantage of this solution might be that you are independent of the format that input-date uses:
<liferay-ui:input-date
name="startDate"
yearParam="startDateYear"
monthParam="startDateMonth"
dayParam="startDateDay"
/>
<liferay-ui:input-date
name="endDate"
yearParam="endDateYear"
monthParam="endDateMonth"
dayParam="endDateDay"
>
<aui:validator name="endDateAfterStartDate" errorMessage="some-error-message">
function(value, fieldNode, ruleValue) {
var result = false;
var startDateYear = parseInt(document.getElementById("<portlet:namespace />startDateYear").value);
var startDateMonth = parseInt(document.getElementById("<portlet:namespace />startDateMonth").value);
var startDateDay = parseInt(document.getElementById("<portlet:namespace />startDateDay").value);
var endDateYear = parseInt(document.getElementById("<portlet:namespace />endDateYear").value);
var endDateMonth = parseInt(document.getElementById("<portlet:namespace />endDateMonth").value);
var endDateDay = parseInt(document.getElementById("<portlet:namespace />endDateDay").value);
if (endDateYear > startDateYear) {
result = true;
} else if (endDateYear == startDateYear) {
if (endDateMonth > startDateMonth) {
result = true;
} else if (endDateMonth == startDateMonth) {
if (endDateDay > startDateDay) {
result = true;
}
}
}
return result;
}
</aui:validator>
</liferay-ui:input-date>
Maybe that helps someone.

Related

Avoid duplicated error messages with ASP.NET CustomValidator

I have an ASP.NET page defined in this way:
<asp:TextBox
ID="_txtExitDate"
ClientIDMode="Static"
runat="server"
Text='<%#Bind("exit_date","{0:dd/MM/yyyy}")%>'
placeholder="gg/mm/aaaa" />
<asp:CompareValidator
runat = "server"
Type = "Date"
Operator = "DataTypeCheck"
Display = "Dynamic"
ControlToValidate = "_txtExitDate"
ErrorMessage = "Exit date invalid."
SetFocusOnError = "true" />
<asp:CustomValidator
Display="Dynamic"
runat="server"
EnableClientScript="true"
ClientValidationFunction="Validate_Exit"
ControlToValidate="_txtExitDate"
ErrorMessage="Exit date should be minor of today date." />
<asp:TextBox
ID="_txtExitTime"
ClientIDMode="Static"
CssClass="input_small"
runat="server"
Text='<%#Bind("exit_time")%>'
placeholder="hh:mm" />
<asp:RegularExpressionValidator
Display = "Dynamic"
ControlToValidate="_txtExitTime"
runat="server"
ErrorMessage="Exit time invalid"
ValidationExpression="^([01][0-9]|2[0-3]|[1-9]):([0-5][0-9]|[0-9])$"
SetFocusOnError = "true" />
<asp:CustomValidator
Display="Dynamic"
runat="server"
EnableClientScript="true"
ClientValidationFunction="Validate_Exit"
ControlToValidate="_txtExitTime"
ErrorMessage="Exit date should be minor of today date." />
The Javascript code that evaluates CustomValidators is:
function Validate_Exit(sender, args) {
var _txtExitDate = $("input[id$='_txtExitDate ']");
var _txtExitTime = $("input[id$='_txtExitTime ']");
if (isBlank(_txtExitDate.val()) || isBlank(_txtExitTime.val())) {
args.IsValid = true;
return;
}
var _sExit = _txtExitDate .val().substring(0, 10) + " " + _txtExitTime.val().substring(0, 5);
var _exit = moment(_sExit, "DD/MM/YYYY HH:mm:ss");
if (_exit.isAfter(moment())) {
args.IsValid = false;
return;
}
args.IsValid = true;
}
The scope of the form is to allow the user to input only valid date/time values. In particular the CustomValidator is intended to allow the input of a couple of combined values that should be minor of the present date-time.
It works as I expect except for a side effect that it's not compromising but it's graphically annoying.
As you can see the CustomValidator is basically the same and it's applied to both textboxes. If the user fails to write a correct date / time combo it show off the message (that's the same message because it's referred to the composed date/time value). In some case the error message is shown 'twice' and this is in part (graphically) horrible but also a little confusing for the user.
Is there a way to avoid duplicating this check and to provide a control for both textboxes so the user is not confused by a double error message?
Best regards,
Mike
You can use a single CustomValidator to validate both fields. Set the ID of that validator but don't set the ControlToValidate property (here I also set the Text property to show an indicator even when the postback is not triggered):
<asp:CustomValidator
ID="cvDateTime"
Display="Dynamic"
runat="server"
Text="Invalid date!"
EnableClientScript="true"
ClientValidationFunction="Validate_Exit"
ErrorMessage="Exit date should be minor of today date." />
You can set the onchange event handler on both TextBoxes to perform the validation as soon as each field is modified:
<asp:TextBox ID="_txtExitDate" onchange="ValidateOnChange();" ... />
<asp:TextBox ID="_txtExitTime" onchange="ValidateOnChange();" ... />
The validation functions could look like this:
function ValidateOnChange() {
var validator = document.getElementById('<%= cvDateTime.ClientID %>');
validator.isvalid = DoValidateDateTime();
ValidatorUpdateDisplay(validator)
}
function Validate_Exit(source, args) {
args.IsValid = DoValidateDateTime();
}
function DoValidateDateTime() {
var _txtExitDate = $("input[id$='_txtExitDate ']");
var _txtExitTime = $("input[id$='_txtExitTime ']");
if (isBlank(_txtExitDate.val()) || isBlank(_txtExitTime.val())) {
return true;
}
var _sExit = _txtExitDate .val().substring(0, 10) + " " + _txtExitTime.val().substring(0, 5);
var _exit = moment(_sExit, "DD/MM/YYYY HH:mm:ss");
return _exit.isSameOrBefore(moment());
}

Deduct Days from RadDateTimePicker

Does anyone know how to deduct 7 days from the current date in RadDateTimePicker using Javascript?
I didn't find any example on how you deduct days from a RadDateTimePicker.
I would love if anyone can show me examples.
Aspx.code
<table border="0">
<tr>
<td>From:</td>
<td>
<telerik:RadDateTimePicker ID="rdpDateFrom" runat="server" Enabled="True" Width="170px">
<Calendar ID="fromCalendar" runat="server" EnableKeyboardNavigation="True">
<SpecialDays>
<telerik:RadCalendarDay Repeatable="Today" ItemStyle-BackColor="lightblue"></telerik:RadCalendarDay>
</SpecialDays>
</Calendar>
<DateInput ID="DateInput3" ToolTip="From Date input" runat="server"/>
</telerik:RadDateTimePicker>
</td>
</tr>
<tr>
<td>To:</td>
<td>
<telerik:RadDateTimePicker ID="rdpDateTo" runat="server" Enabled="True" Width="170px">
<Calendar ID="toCalendar" runat="server" EnableKeyboardNavigation="True" />
<DateInput ID="DateInput4" ToolTip="To Date input" runat="server"/>
</telerik:RadDateTimePicker>
</td>
</tr>
</table>
JavaScript Code
function OnClientSelectedIndexChanged(sender, eventArgs) {
var range = $find("<%= rcbDateTime.ClientID %>");
var item = eventArgs.get_item();
var From = $find("<%= rdpDateFrom.ClientID %>");
var To = $find("<%= rdpDateTo.ClientID %>");
var todaysDate = new Date();
todaysDate.setDate(todaysDate.getDate());
if (item.get_value() == "1") { //Today's Date
From.set_selectedDate(todaysDate);
To.set_selectedDate(todaysDate);
}
if (item.get_value() == "2") { //Last 7 days
//Calculation
From.set_selectedDate(
To.set_selectedDate(todaysDate);
}
}
More of a comment than an answer:
If I understand the issue (and maybe I don't, there's documentation here), you need to pass date objects to the set_selectedDate method. There seems to be some typos in the OP, so maybe best to just post the corrected code, something like:
var itemValue = item.get_value();
var todaysDate = new Date();
var weekAgo = new Date(+todaysDate);
weekAgo.setDate(weekAgo.getDate() - 7);
//Today's Date
if (itemValue == "1") {
From.set_selectedDate(todaysDate);
To.set_selectedDate(todaysDate);
//Last 7 days
} else if (itemValue == "2") {
From.set_selectedDate(todaysDate);
To.set_selectedDate(weekAgo);
}
If there are more conditions, you might consider using switch instead of if..else.

0x800a138f - JavaScript runtime error: Unable to get property 'value' of undefined or null reference

i have written a javascript code to compare 2dates from 2 textboxes
function CompareDates() {
var fdate = document.getElementById('txtFromDate');
var edate = document.getElementById('txtToDate');
var FromDate = fdate.value.split('/');
var EndDate = edate.value.split('/');
var val = 'false';
if (parseInt(FromDate[2]) < parseInt(EndDate[2])) {
val = 'true';
return true;
}
else if (parseInt(FromDate[2]) == parseInt(EndDate[2])) {
if (parseInt(FromDate[0]) < parseInt(EndDate[0])) {
val = 'true';
return true;
}
else if (parseInt(FromDate[0]) == parseInt(EndDate[0])) {
if (parseInt(FromDate[1]) <= parseInt(EndDate[1])) {
val = 'true';
return true;
}
}
}
if (val == "false") {
alert("FromDate Always Less Than ToDate");
return false;
}
}
and html code is
<asp:TextBox ID="txtFromDate" runat="server" Width="150px" />
<ajaxToolkit:CalendarExtender CssClass="MyCalendar" runat="server"
ID="ceFromDate"
TargetControlID="txtFromDate"
Format="dd/MM/yyyy" />
<asp:TextBox ID="txtToDate" runat="server" Width="150px" />
<ajaxToolkit:CalendarExtender CssClass="MyCalendar" runat="server"
ID="ceToDAte"
TargetControlID="txtToDate"
Format="dd/MM/yyyy" />
<asp:Button ID="btnGenerate" runat="server" CssClass="button"
Text="Generate" OnClientClick="if(!CompareDates()) return false;"
OnClick="btnGenerate_Click" />
the problem is that the page is running well in chrome but when i run my application in IE it throw an error
0x800a138f - JavaScript runtime error: Unable to get property 'value'
of undefined or null reference
please help me to overcome from this problem.
The error is here:
var fdate = document.getElementById('txtFromDate');
var edate = document.getElementById('txtToDate');
The problem is that txtFromDate and txtToDate are the server name of controls, not the client name (look the source of page from the browser).
Try this:
var fdate = document.getElementById('<%=txtFromDate.ClientID%>');
var edate = document.getElementById('<%=txtToDate.ClientID%>');
If your javascript is located in an external JS file (which it should), the posted solutions will not work. But you could give the text fields a unique class name and modify your code as such:
<asp:TextBox ID="txtFromDate" runat="server" Width="150px" CssClass="txtFromDate" />
<asp:TextBox ID="txtToDate" runat="server" Width="150px" CssClass="txtToDate" />
and your javascript:
var fdate = document.getElementsByClassName('txtFromDate')[0];
var edate = document.getElementsByClassName('txtToDate')[0];
Please try this
document.getElementById('<%=txtFromDate.ClientID %>')
Change your code like following:
function CompareDates() {
var fdate = document.getElementById('<%=txtFromDate.ClientID %>');
var edate = document.getElementById('<%=txtFromDate.ClientID %>');
var FromDate = fdate.value.split('/');
var EndDate = edate.value.split('/');
var val = 'false';
if (parseInt(FromDate[2]) < parseInt(EndDate[2])) {
val = 'true';
return true;
}
else if (parseInt(FromDate[2]) == parseInt(EndDate[2])) {
if (parseInt(FromDate[0]) < parseInt(EndDate[0])) {
val = 'true';
return true;
}
else if (parseInt(FromDate[0]) == parseInt(EndDate[0])) {
if (parseInt(FromDate[1]) <= parseInt(EndDate[1])) {
val = 'true';
return true;
}
}
}
if (val == "false") {
alert("FromDate Always Less Than ToDate");
return false;
}
}
You are missing the # for your id reference.
Change from:
var fdate = document.getElementById('txtFromDate');
to:
var fdate = document.getElementById('#txtFromDate');
I was wrong about the above statements.
I was able to fix the same error in my jquery code where I was missing the #. getElementById does not need this special character.

How to auto format textbox inputs

<tr>
<td><label>Birthdate</label>
<input type="text" placeholder="mm/dd/yyyy" name="birthdate" maxlength="10"/>
</td>
</tr>
Well, my code is working but I want my "input type text" to auto format like a date (html 5 input type=date) because in my Servlet I convert it to Age.
The problem is that, if I use the "input type=date" the conversion is error so I decided to use "input type=text" and it's working. So is it possible to auto put "/" in this format "mm/dd/yyyy"? For example, if the user input 2 character an "/" will auto input etc.
Servlet for birthdate to Age
String birthdate = request.getParameter("birthdate");
int monthDOB = Integer.parseInt(birthdate.substring(0, 2));
int dayDOB = Integer.parseInt(birthdate.substring(3, 5));
int yearDOB = Integer.parseInt(birthdate.substring(6, 10));
DateFormat dateFormat = new SimpleDateFormat("MM");
java.util.Date date = new java.util.Date();
int thisMonth = Integer.parseInt(dateFormat.format(date));
dateFormat = new SimpleDateFormat("dd");
date = new java.util.Date();
int thisDay = Integer.parseInt(dateFormat.format(date));
dateFormat = new SimpleDateFormat("YYYY");
date = new java.util.Date();
int thisYear = Integer.parseInt(dateFormat.format(date));
int calAge = thisYear - yearDOB;
if (thisMonth < monthDOB) {
calAge = calAge - 1;
}
if (thisMonth == monthDOB && thisDay < dayDOB) {
calAge = calAge - 1;
}
String age = Integer.toString(calAge);
Update in the form
<tr>
<td><label for="inputName">Birthdate</label>
<input type="text" placeholder="mm/dd/yyyy" id="input_date" name="birthdate" maxlength="10" />
</td>
</tr>
Update in the source
<script src="../scripts/formatter.js"></script>
<script src="../scripts/formatter.min.js"></script>
<script src="../scripts/jquery.formatter.js"></script>
<script src="../scripts/jquery.formatter.min.js"></script>
Added Script
<script>
$('#input_date').formatter({
'pattern': '{{99}}/{{99}}/{{9999}}',
'persistent': true
});
</script>
I also tried the javascript but it's not working...
I've been watching a project on GitHub (and providing feedback to improve it) for just such kind of formatting called formatter.js http://firstopinion.github.io/formatter.js/demos.html This might be just the thing you're looking for.
This wouldn't stop you from typing in dates like the 53rd of May... but it will help you format.
new Formatter(document.getElementById('date-input'), {
'pattern': '{{99}}/{{99}}/{{9999}}',
'persistent': true
});
or
$('#date-input').formatter({
'pattern': '{{99}}/{{99}}/{{9999}}',
'persistent': true
});
I have an alternative that works with a jquery-ui datepicker, without formatter.js. It is intended to be called from the keyup and change events. It adds zero padding. It works with various supported date formats by constructing expressions from the dateFormat string. I can't think of a way to do it with fewer than three replaces.
// Example: mm/dd/yy or yy-mm-dd
var format = $(".ui-datepicker").datepicker("option", "dateFormat");
var match = new RegExp(format
.replace(/(\w+)\W(\w+)\W(\w+)/, "^\\s*($1)\\W*($2)?\\W*($3)?([0-9]*).*")
.replace(/mm|dd/g, "\\d{2}")
.replace(/yy/g, "\\d{4}"));
var replace = "$1/$2/$3$4"
.replace(/\//g, format.match(/\W/));
function doFormat(target)
{
target.value = target.value
.replace(/(^|\W)(?=\d\W)/g, "$10") // padding
.replace(match, replace) // fields
.replace(/(\W)+/g, "$1"); // remove repeats
}
https://jsfiddle.net/4msunL6k/
use datepicker api from jquery
here is the link Datepicker
and here is the working code
<tr>
<td><label>Birthdate</label>
<input type="text" placeholder="mm/dd/yyyy" name="birthdate" id="birthdate" maxlength="10"/>
</td>
</tr>
<script>
$(function() {
$( "#birthdate" ).datepicker();
});
</script>
EDIT
$("input[name='birthdate']:first").keyup(function(e){
var key=String.fromCharCode(e.keyCode);
if(!(key>=0&&key<=9))$(this).val($(this).val().substr(0,$(this).val().length-1));
var value=$(this).val();
if(value.length==2||value.length==5)$(this).val($(this).val()+'/');
});
this is the code that you may need
here is the fiddled code
user2897690 had the right idea but it didn't accept Numpad numbers. So took their javascript and modified it to work.
Here is my interpretation of their code with the added feature.
$("input[name='birthdate']:first").keyup(function(e){
var chars = [48,49,50,51,52,53,54,55,56,57,96,97,98,99,100,101,102,103,104,105];
var key=chars.indexOf(e.keyCode);
console.log(key);
if(key==-1)$(this).val($(this).val().substr(0,$(this).val().length-1));
var value=$(this).val();
if(value.length==2||value.length==5)$(this).val($(this).val()+'/');
});

Validation Dates using Javascript & ASP.Net

I have an ASP.Net form in which users can choose the date from Calendar Extender control, I have 2 fields for the date (FromDate & ToDate).
I want to validate the following using javascript:
FromDate should be always less than ToDate
FromDate & ToDate should not be less than today's date.
If both conditions are true, I would like then to call a method from the codebehind which will calculate the total number of days within the selected period excluding the weekends and display it to the user (this method works fine).
In the code below I tried __doPostBack to fire the codebehind method when the two previously mentioned conditions are met. It fires the codebehind method but then javascript variables becomes incorrect (compareDate variable is always increment on each function call & postback) and thus all the result becomes incorrect.
*Below is the current method I use to validate the date using Javascript, it's fired from OnClientDateSelectionChanged event from both textboxes's calendar extender controls *
<script type="text/javascript">
var fromDate = new Date();
var toDate = new Date();
function checkDate(sender, args) {
if (sender.get_id() == 'CalendarExtenderFrom') {
fromDate = sender._selectedDate;
}
else if (sender.get_id() == 'CalendarExtenderTo') {
toDate = sender._selectedDate;
}
// Check if selected date is less than today's date
var todayDate = new Date();
var year = todayDate.getFullYear();
var month = todayDate.getMonth();
var day = todayDate.getDate();
var dateOnly = new Date(year, month, day);
if (sender._selectedDate < dateOnly) {
alert("You cannot select a day earlier than today!");
sender._textbox.set_Value("");
return;
}
// Check if FromDate > ToDate
if (document.getElementById('TextBoxDateOfLeave').value != "" && document.getElementById('TextBoxDateOfReturn').value != "") {
var compareDate = new Date(fromDate.getFullYear(), fromDate.getMonth(), (fromDate.getDate()) + 1, 00, 00, 00, 00);
if (toDate < compareDate) {
alert("(Return Date) should be greater than (Travel Date)");
sender._textbox.set_Value("");
return;
}
}
// If both conditions are met
window.__doPostBack('__Page', '');
}
</script>
ASP.Net Controls:
<asp:TextBox ID="TextBoxDateOfLeave" runat="server" ClientIDMode="Static" ontextchanged="CalculateLeaveDays"></asp:TextBox>
<asp:CalendarExtender ID="CalendarExtenderFrom" runat="server" Enabled="True" Format="dd/MMM/yyyy" TargetControlID="TextBoxDateOfLeave" OnClientDateSelectionChanged="checkDate" />
<asp:TextBox ID="TextBoxDateOfReturn" runat="server" ClientIDMode="Static" ontextchanged="CalculateLeaveDays"></asp:TextBox>
<asp:CalendarExtender ID="CalendarExtenderTo" runat="server" Enabled="True" Format="dd/MMM/yyyy" TargetControlID="TextBoxDateOfReturn" OnClientDateSelectionChanged="checkDate" />
Please let me know if there is a way to achieve this.
Thank you,
Were you looking for something like this? I added a Fiddle here. I used the jquery ui date picker, but you can use any datepicker of your choice, provided the values are in 'yyyy/mm/dd' or 'mm/dd/yyyy' I think

Categories

Resources