Angular event detection for datepicker close - javascript

I have just started using angular and in general love it. I have a UI requirement to show a date as text, then when you click on the text, it shows a date picker instead. Then when you select a date it goes back to text. Sounds simple.
I have tried a few variations on the below code the object being edited holds a value called editdate, clicking on the text box changes this to true and hides the text and shows the editor. This works fine, the problem is hiding the date picker. I tried adding ng-blur to the datepicker to cause the box to hide when it looses focus, but this was very intermittent as to if it worked. I then tried ng-Mouseleave but the box closed when I moved the mouse pointer into the date picker from the text box.
<td colspan="7">
Required Date : <span ng-click="item.editdate=true; item.delayeditclose = true;" ng-show="!item.editdate">{{item.dueDate.toDateString()}}</span>
<input type="date" ng-blur="item.editdate=false" ng-click="item.switcheditdate(item.delayeditclose)" ng-show="item.editdate" class="datepick" ng-model="item.dueDate" ng-focus="selectPart(item.partNumber)" />
</td>
The javascript is initialized as:
for (var i = 0; i < data.items.length; i++) {
item = data.items[i];
item.showExpanded = false;
item.editdate = false;
item.delayeditclose = true;
item.switcheditdate = function (delayclose) {
if (!delayclose) {
this.editdate = !this.editdate;
this.delayeditclose = true;
}
this.delayeditclose = false;
};
items.push(item);
}
I have now moved onto the above which almost does the job. The new issue being html5 date pickers seem to have a x to close them down. This hides the whole box and not just the picker part. If this happens I want to show the text of the date rather than what I get now which is nothing. Does anyone know of how I can capture this close event and revert back to the text or suggest a better approach to the problem?
I have lots of items each one is in its own row in a table
I am using angular 1.3 beta 8
thanks for looking
Andy

The reason why you are getting nothing is because when you click x what happens is that the date value gets cleared so then your date view is an empty string. What you can do is set a condition to display a string such as "Click to Edit" when the date is empty.
Taking just what you have above, one way of doing it is by adding an element and a flag in your date "view". So change this:
Required Date : <span ng-click="item.editdate=true; item.delayeditclose = true;" ng-show="!item.editdate">{{item.dueDate.toDateString()}}</span>
To:
Required Date :
<span ng-click="item.editdate=true; item.delayeditclose = true;" ng-show="!item.editdate">
<span>{{item.dueDate.toDateString()}}</span>
<span ng-show="!item.dueDate">Click to Edit</span>
</span>
The directive way
Now in my opinion I think it's much better to use a directive for this. It would simplify your logic and is much easier to re-use. I created a plunker which shows my implementation using a directive.
Answer to question in title
To answer the question posed by your title, when using the html5 date picker, you can't detect when it is closed (or even when it is opened). See this answer and the linked Quick FAQs on input[type=date]

Related

How to set datepicker using webdriverIO?

I have a task where I need to automate the booking.com page, and one of the tasks is to select check-in and check-out dates. How I can do this? I automated , that I can open calendar, but I don't know how to select dates.
Here is my code
Cucumber step
And user selects dates from "2020-06-16" to "2020-06-26"
BookingStep
When('user selects dates from {string} to {string}',()=>{
BookingPage.checkInOut.click();
browser.debug(); });
Booking page
class BookingPage{
get whereAreYouGoingTextBox(){return $('#ss')};
get checkInOut(){return $('div.xp__dates-inner')}; }export default new BookingPage();
Note: My answer is a solution for the ability to set a value in the date field, and only interact with the cancel link on the date picker object.
I battled this for a while and came up with a solution that works for me, I hope it works for you also.
First when I inspect the datepicker object, it generates a random XPATH/CSS Selector. As a result if you inspect & copy the selector and try to use it in your next test, it will fail since the xpath/selector is randomly generated. I got around this issue by identifying a unique css ID that lived above the datepicker element, and used that as my starting point. Then I looked at the html path from that point to the datepicker input tag, and I appended that path. This solved the first problem of not being able to set a value in the date picker text field. Here is an example using xpath:
//*[#id="filtersSideBar"] - This is the unique ID found above the datepicker
/div[2]/div/input - This is the path to the date picker from the unique ID
$('//*[#id="filtersSideBar"]/div[2]/div/input').waitForClickable(3000);
$('//*[#id="filtersSideBar"]/div[2]/div/input').setValue('2020-01-01');
Now that you have a date inside the date picker field, you have to close the datepicker object. I had to use Javascript to accomplish this. First open the datepicker object, then inspect the 'Cancel' link element. Copy the CSS Selector ID. Lets say it ends up being #cancelLink
Now you run this code:
browser.execute(() => document.querySelector('#cancelLink').click());
Which will then close the datepicker object so that you can proceed with your testing.
Here is my actual code:
class DataSearchSortAndDateRangePage {
get startDate() { return $('//
[#id="filtersSideBar"]/div[2]/div/div[2]/div[1]/div/input'); }
setStartDate(date) {
this.startDate.waitForClickable( { timeout: browser.config.timeOutValue } );
this.startDate.setValue(date);
browser.execute(() => document.querySelector('body > div.md-datepicker-dialog.md-theme-default > div.md-datepicker-body > div.md-dialog-actions.md-datepicker-body-footer > button > div > div').click());
}
}
export default new DataSearchSortAndDateRangePage();
I hope this helps out =)

Access Selected Date from dynamically created Calendar Control asp/javascript/VB.net

UPDATE: To anyone who still may read this, I used a completely different way of doing this. With AjaxToolkit's Calendar Extender, I was able to easily add a calendar dynamically and use Javascript to change the format of different date inputs so that calendar extender could read it. Highly recommend you go the AjaxToolkit route if you are trying to do something similar to me.
I have dynamically created a Calendar control(asp:Calendar), Buttons, and dropdown lists for a Comment Class. The Comment Class will always have a textbox in it, but if the ID/attribute label of the textbox is DOB or birthday or something similar, these other controls get dynamically created.
So far, the calendar, dropdown lists, and one of the buttons works, but I am have trouble with the last button. Currently, I dynamically add a script that is used for one of the buttons to show and hide the div that contains that Calendar, dropdown lists, and relevant buttons, which works amazingly. I am trying to add another script trigger on a button press to take the selected date from the Calendar and put it in the textbox.
Right now, I am just trying to get access to the Calendar. I am using code that looks like this:
function use_calendarDate(){
var calendarDate = '<%=question128_Cal1.SelectedDate%>';
alert(calendarDate);
}
I found this function in another question similar to this, but instead of getting the date, it just puts <%=question128_Cal1.SelectedDate%> as a string into the alert box.
This LINK shows exactly what I am trying to do, but I get a different result. Can anyone help me with what I am doing wrong here?
Interestingly, when I use
var calendarDate = question128_Cal1.SelectedDate;
OR
var calendarDate = question128_Cal1.value;
My alert box tells me undefined.
Thanks in advance.
In case it is needed, my calendar control is created like this:
In Page_Init
Dim calendar1 As New Calendar
Call BuildCalendar(calendar1)
calendarDiv.Controls.Add(calendar1)
Here is the function referenced above.
Private Sub BuildCalendar(ByRef calendar1 As Calendar)
calendar1.ID = "Cal1"
calendar1.SelectedDate = DateTime.Today
calendar1.Attributes.Add("runat", "server")
calendar1.Attributes.Add("OnClientDateChanged", "onDateChange")
calendar1.Attributes.Add("borderwidth", "2px")
calendar1.Attributes.Add("BackColor", "White")
calendar1.Attributes.Add("width", "200px")
calendar1.Attributes.Add("ForeColor", "Black")
calendar1.Attributes.Add("Height", "180px")
calendar1.Attributes.Add("Font-Size", "8pt")
calendar1.Attributes.Add("Font-Names", "Verdana")
calendar1.Attributes.Add("BorderColor", "#999999")
calendar1.Attributes.Add("BorderStyle", "Outset")
calendar1.Attributes.Add("DayNameFormat", "FirstLetter")
calendar1.Attributes.Add("CellPadding", "4")
calendar1.Attributes.Add("ShowNextPrevMonth", "True")
calendar1.Attributes.Add("SelectionMode", "Day")
calendar1.Attributes.Add("ShowTitle", "false")
calendar1.Attributes.Add("OnSelectionChanged", "Calendar_SelectionChanged")
calendar1.TodayDayStyle.ForeColor = Drawing.Color.Black
calendar1.Attributes.Add("todaydaystyle-backcolor", "#cccccc")
calendar1.Attributes.Add("selectorstyle-backcolor", "#cccccc")
calendar1.NextPrevStyle.VerticalAlign = VerticalAlign.Bottom
calendar1.Attributes.Add("dayheaderstyle-font-size", "7pt")
calendar1.Attributes.Add("dayheaderstyle-font-bold", "true")
calendar1.Attributes.Add("dayheaderstyle-backcolor", "#cccccc")
calendar1.Attributes.Add("selecteddaystyle-font-bold", "true")
calendar1.Attributes.Add("selecteddaystyle-forecolor", "White")
calendar1.Attributes.Add("selecteddaystyle-backcolor", "#666666")
calendar1.Attributes.Add("titlestyle-font-bold", "true")
calendar1.TitleStyle.BorderColor = Drawing.Color.Black
calendar1.Attributes.Add("titlestyle-backcolor", "#999999")
calendar1.Attributes.Add("weekenddaystyle-backcolor", "#ffffcc")
calendar1.OtherMonthDayStyle.BackColor = Drawing.Color.Gray
End Sub
Is it question128_Cal1 or question128_Calendar1 ? Your function use_calendarDate() refers to the first. Typo ?
Interestingly, when I use
var calendarDate = question128_Calendar1.SelectedDate;
OR
var calendarDate = question128_Calendar1.value;
My alert box tells me undefined.
That's because the client script has no knowledge of what 'question128_Calendar1' is. That is a server-side ID.
Is there a reason why you can't use markup to define the calendar instead that rather large 'BuildCalendar' function? You're making a bit of a maintenance nightmare by doing that, IMO.

Input field disabled, but glyphicon is still clickable

I am writing a ReactJS application, and I want to disable the input on a date/time field, which includes the react-bootstrap-datetimepicker. Disabling the input field works fine, but the glyph used to bring up the datepicker, when clicked, is still active, and it allows the user to select a date, which is added to the input field. It just seems to prevent typing.
Does anyone know a way around this?
<DateTimeField
inputFormat='HH:mm'
data-hour-format="24"
mode='time'
name="formInputTime"
id={inputID}
defaultText={this._getICEField(i-1, "time")}
onChange={this._generateEventHandler(i-1, "time")}
inputProps={{disabled: readOnly}}
/>
In this image the input field is set as disabled, but the calendar still appears, and a date can be set:
Here is an example on jsfiddle.
Well, the control does not support this as of now (and maybe it shouldn't either), so you should not run the
$element.datetimepicker()
on those input fields, which are disabled. You can check the disabled state programmticaly like this:
var $startDate = $('#startDate');
if (!$startDate.prop('disabled')) {
$startDate.datetimepicker()
}
Try this one, I have just updated your code: JsFiddle.
Relevant code:
if($("input[name=startDate]").attr('disabled') != 'disabled') {
jQuery("#startDate").on("dp.change",function (e) {
jQuery('#endDate').data("DateTimePicker").setMinDate(e.date);
});
jQuery('#startDate').datetimepicker();
}

Setting default time value for datetime-local

I am using this html tag as a datetime picker:
<input type="datetime-local">
I want to be able to set a default value for the time part only so if
someone inserts a date and doesn't insert the time (leaves it as --:--:--) then I will be able to set it as 00:00:00 for example.
The problem is I know only how to set the a value including both the date and time and if someone inserts only a date w/o the time I can't read that value and getting a blank value.
Is it possible to overcome that? or is there any other datetime picker I could use for the described scenario?
We can not change the behavior of browser against an element. So this is an answer to the second question that if there is another solution for this scenario. I used two separate fields of date and time which control a single datetime-local field.
Please note that the date filed has no value unless the field is totally completed. So I used blur event instead of keyup or change.
$(document).ready(function() {
var mydate, mytime, mystring;
$("#dateField").blur(function() {
if ($(this).val()) {
setResult();
}
})
$("#timeField").change(function() {
setResult()
})
})
function setResult() {
mydate = $("#dateField").val();
mytime = $("#timeField").val();
mystring = mydate + 'T' + mytime;
document.getElementById('resultField').value = mystring;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="dateField" type="date"><input id="timeField" type="time" value="18:30">
<br>
<strong>Result</strong>:
<br>
<input id="resultField" type="datetime-local">
Footnote 1:
The change listener works on time field (when has default value) but I noticed a vague behavior in google-chrome that if you change the value of time filed by mouse clicks, the change event is triggered after mouseOut! This has no effect on the answer above.
Footnote 2:
You can hide the result field inside a display:none div.

Multi Dates Picker Bug?

I've been trying to add a date picker to my site that allows users to pick multiple non-concurrent dates. Multidatespicker appears to do what I want but i've got to a point where I think I have discovered a bug, particularly with it's AltField, which is confirmed here. The bug seems to stop the altfield's values showing. If you visit the Multidatespicker demo and inspect the altfield you'll see that while it appears empty the values are showing in the code.
The issue this presents for me is that I can't edit previously selected dates when returning a record from my App/DB. When passing the value of altfield back to my Rails App for database storage I only receive the hidden values shown in the code.
If I can get the altfield to correctly show these values and allow me to edit them via the date selector, then I should be amend within my app's backend.
Note the suggested fix on the github link above does not solve this issue - it only enables rendering dates in 'dateVar' as being selected in the picker....it does nothing to show values in altField.
Has anyone used this and had the same problem and solved it?
Does anyone know how to fix it?
OR
Can anyone suggest a good alternative that will work nicely with a Rails 3 App using Twitter Bootstrap. It's very important that i'm able to select multiple non-concurrent dates. I've searched quite extensively but MultiDatesPicker seems to be one of the only options I can find.
The problem is that Multidatespicker is not listening #altField so we need to create our own listener to add/remove dates.
The idea is to add values to a hidden or readonly input and add/remove dates by an other. This prevent the customer to add dates in #altField and getting them overwritten by the plugin.
HTML
<input type="text" id="date">
<button type="button" id="addDate">Add dates</button>
<button type="button" id="removeDate">Remove dates</button>
<div class="ui-state-error" id="error"></div>
<br />
<input type="text" id="altField" readonly value="2013-08-30,2013-08-31">
JAVASCRIPT
And with javascript we simply add the date with a button (could be on keyup or anything your imagination can imagine :)
var dates = $('#altField').val().split(',');
$('#datepicker').multiDatesPicker({
dateFormat: "yy-mm-dd",
addDates: dates,
altField: '#altField'
});
$('#addDate, #removeDate').on('click', function() {
try {
var $date = $('#date');
var addOrRem = $(this).attr('id') === "addDate" ? 'addDates' : 'removeDates';
$('#datepicker').multiDatesPicker(addOrRem, $date.val());
$date.val('');
} catch (e) {
var $error = $('#error');
$error.html(e).slideDown();
setTimeout(function() {
$error.slideUp();
}, 2000);
}
});
jsFiddle
I have scanned the source of MultiDatesPicker. I don't find any method which set the date from the #altfield. So it is not a bug it is missing.
I also do not understand the difference between the preselected dates and the altfield.
I think you can do what you want with a combination of preselect and the altfield:
html
<div id="with-altField"></div>
<input type="text" id="altField" value="08/22/2013,08/21/2013">
</div>
javascript
//first read the values of the #altfield
var dates = $('#altField').val().split(',');
//second set your multiDatesPicker with the dates of step 1 and an altfield
$('#with-altField').multiDatesPicker({
dateFormat: "mm/dd/yy",
addDates: dates,
altField: '#altField'
});
nb load the javascript on document ready

Categories