I'm new to HTML5 and Knockout.js I am facing an issue in datetime-local control.
Here is the HTML datetime-control I'm using
<script type="text/html" id="DATE.template">
<input type="datetime-local" data-bind="value: Prompt.CurrentValue, enable: Prompt.IsEnabled, valueUpdate: 'input'" />
</script>
Here is the Save button and it's binded to savecommand to javascript file.
<div class="buttons-wrapper">
<button class="button save-idoc-button" data-bind="command: SaveIdocCommand, activity:SaveIdocCommand.isExecuting">Save</button>
<button class="button cancel-save-button" data-bind="command: CancelIdocCommand, activity:CancelIdocCommand.isExecuting">Cancel</button>
</div>
When I enter the date without entering any time, date is being passed null on SAVE. I understand it's a incomplete date, hence the browser considers it a invalid date, but the entered date is not saved. The Selected date is binded to Prompt.CurrentValue; When user enters an incomplete date (without time), prompt.currentvalue is null, and I get a tooltip message on the datetime control that "Please enter a valid date or date entered is incomplete". (browser validates and provides i think)
What is the best approach to take?
a. should we need to provide the custom validation and disable the SAVE button, until the datetime-local control has a valid value. If so, how we can achieve in html5/knockout.js?
b. Is there a way to disable the browser validation of datetime-local control, so that the date can be passed even though time is not entered.? (I tried with using "novalidation", but it didn't work)
c. any other better approach?
EDIT:
Here is the computed observable for validation in viewmodel; Prompt.CurrentValue is the value to binded to UI controls. When it's date control, this validationerror doesn't work.
> hasValidationErrors = ko.computed(function () {
> //loop through fields and filter out fields that are set up with validation and has invalid data.
> var invalidFieldsArray=ko.utils.arrayFilter(fields(), function (field) {
> return !_.isUndefined(field.Prompt) && !_.isNull(field.Prompt)
> && (
> ((_.has(field.Prompt.CurrentValue,"isValid"))&&!field.Prompt.CurrentValue.isValid())
>
> ||
> ((_.has(field.Prompt.AdditionalData, "isValid")) && !field.Prompt.AdditionalData.isValid())
> );
> });
> return invalidFieldsArray.length > 0;;
> })
,
this selected datetime-local value is not binded (to the corresponding viewmodel: Prompt.CurrentValue),until the user selects the date and enters the full time ... I understand browser does this validation for this control. how can computed observable recognize this invalidity of date control ? (as value is not passed until the value is valid)
Is there a way to disable the browser validation of datetime-local control, so that the date can be passed even though time is not entered
If possible, can you use a combination of <input type="date"> and <input type="time"> instead? (and use the textInput binding while you're at it)
A couple of things - if you are submitting the form to a server your <inputneeds a name attribute to save properly. And you can preset it to a current value if you want e.g. <input name="date" etc.
You need to show your viewModel if you want help with that.
Re validation - a simple Google search shows this validation suite https://github.com/Knockout-Contrib/Knockout-Validation
However, in Javascript anything to do with dates (date validation, date presentation, date tranformation) you should be using Moment.js
EDIT:
Will have a look at your code above when I get a chance. Please note value is not a good binding for date inputs. I suggest you change
data-bind="value: Prompt.CurrentValue, enable: Prompt.IsEnabled, valueUpdate: 'input'"
to
data-bind="textInput: Prompt.CurrentValue, enable: Prompt.IsEnabled"
EDIT 2:
OK, so date-time is NOT supported in ANY version of Firefox, IE, or Safari - it is a pure text input.
Check out https://github.com/Knockout-Contrib/Knockout-Validation/wiki/Native-Rules and Knockout date validation not working correctly, but I think it is best to switch to moment.js (isValid()) and stick to a specifically formatted date string or use a jquery style popup calendar.
Related
I have input fields which are dates (no time) and I use an input field with type=date for date selection. The value is tied to the model using the asp-for attribute. When a user incorrectly selects a FROM date that is later than the TO date, my action reverses the dates so they are displayed the correct way round. However, the HTML values maintain the previously selected values and not the newly posted, corrected values. In effect, the asp-for is ignoring the latest value in the model.
The Model property is a DateTime and not a string and I don't use DataAnnotations in this case.
<input type="date" asp-for="DateFrom"
min="#Model.EarliestDate.ToHtmlInputDate()"
max="#Model.LatestDate.ToHtmlInputDate()"
onchange="$('form').submit();" class="form-control">
I found a simple fix for the issue. I'm not sure if treating the value as a string rather than a DateTime will also be a cure but that rather gets away from the fact that fundamentally it is a date.
I already have a class extension helper to get the required HTML format date so I set this string result to the VALUE of the element and this appears to work in all scenarios
<input type="date" value="#Model.DateFromString" asp-for="DateFrom" min="#Model.EarliestDate.ToHtmlInputDate()" max="#Model.LatestDate.ToHtmlInputDate()" onchange="$('form').submit();" class="form-control">
I have a Component in my Angular project that shows a graph up to a particular date as picked by the user. The value in the date input must be a valid date. So when clicking the x button on the date picker, it should go to the current date and not be blank.
This is the html:
<input class="form-control input-sm" type="date" name="endDate"
[ngModel]="endDate | date:'yyyy-MM-dd'" (ngModelChange)="setEndDate($event);">
and the following code in the Component TS file:
endDate = new Date();
setEndDate(newValue) {
if(newValue) {
this.endDate = newValue;
return;
}
this.endDate = new Date();
}
What I can't get my head around is that sometimes it works and sometimes it doesn't. Specifically, when the date in the picker is not the current date, clicking the x results in it becoming the current date as intended. When the date in the picker is the current date, it goes blank and shows mm/dd/yyyy. It should just stay on the current date.
From testing it looks like the value is being set, but the picker does not update for some reason. I've tried changing the binding but this only resulted in it breaking completely. Any light that can be shed on why this works sometimes but not other times would be appreciated.
stackblitz: https://stackblitz.com/edit/angular-oep55t
I use a viewChild for set the value of the nativeElement. Looks like endDate was never pass throught the input date after clear the value. I used the datePipe in the ts file in order to get the date formatted. Don't forget to add the datepipe into the providers in your module.
https://stackblitz.com/edit/angular-268qje
Let me know if it's ok for you.
I'm using Angular (4) and as you will see, I'm new to this game!
I've got data coming from a server backend ok, dates are being parsed into TS objects ok by my service.
However, when I include a date type input, I get a value of 'dd/mm/yyyy' rather that the date from the model (Browser is Chrome).
In my template:
<input [(ngModel)]="anObject.dateProperty"
type="date" name="dateProperty" required="required">
I have tried using placeholder and value attributes on the input element.
Else where in the same template file this displays the date as I would expect, so I'm comfortable the value is set:
{{anObject.dateProperty | date:'dd-MM-yyyy'}}
What is the Angular way of rendering the value of a date into an HTML input field?
When using a HTML5 date field, every key input triggers the change event on the field on Chrome.
See jsFiddle and try to input the date manually to see the effect:
https://jsfiddle.net/hx3zcenj/4/
document.getElementById('dateFilter').addEventListener('change', function(){
document.getElementById('msgContainer').innerHTML += 'Change triggered<br>';
}); //triggers on every keypress
I would like this event to trigger like it does in a normal text field, i.e. after either selecting the date from the picker or on blur. I don't want it to trigger every time I input a character.
This is mostly relevant for Chrome, since other browsers deal with this field in different ways.
Once the date input has all the three fields, i.e. dd, mm and yyyy; it starts triggering. Which is logical as the date has all the fields and the date is a valid date, though might not be valid for business case.
You can bind the blur event which will do your job. And provide the other attributes like min and max which will also trigger errors.
And if you are going to bind the change event, then first thing you should do is check that data is valid and in the range.
How about using the focusout event instead. This will trigger when they leave the field/change the focus
document.getElementById('dateFilter').addEventListener('focusout', function() {
document.getElementById('msgContainer').innerHTML += 'Change triggered<br>';
});
<input type="date" id="dateFilter">
<div id="msgContainer"></div>
I have an HTML form that includes type=date fields. Each date field has a min/max value set as a basic sanity check since my users like to type into the form (rather than use date pickers) and they often type dates like "4/17/0213".
The form is submitted by a jquery ajax call which is triggered by a form submit.
All users are using Chrome as a browser.
When they type in a date completely that is out of range, date range validation works as it should. When they merely change the year, or the year and one other part of the date (month or day, but not both), in an existing date so that it ends up outside the valid range, Chrome does not give them a validation error. Instead, it silently "corrects" the year back to what it was previously so that it stays in the valid date range. This results in garbage values getting silently submitted to the database.
I've tried writing my own validation routine in javascript, but it seems that the problem is that the underlying data value doesn't change to the invalid year, so trying to get it and check it is a waste of time. As far as Chrome is concerned, the invalid year just wasn't typed.
Does anyone know a workaround for this?
EDIT: I have included some code to demonstrate part of the problem.
<!DOCTYPE HTML>
<html>
<head>
<title>Date bug test</title>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
$(document).ready(function(){
$(document).on("submit", "FORM", function(){
$("#dateshow").html("Date entered was: " + $("input[name=foo]").val());
return true;
});
});
</script>
</head>
<body>
<form action="javascript:void(0)">
<input type=date name="foo" min='1980-01-01' max='2080-01-01' />
<input type=text name="bar">
<input type=submit>
</form>
<div id=dateshow></div>
</body>
To demonstrate:
Save this to an html file and open in Chrome
Enter a date between 1980 and 2080 into the date field and submit
Date will be shown as submitted.
Select ONLY THE YEAR in the date field and change it to a value outside the valid range
Click submit again.
Note that the date submitted does not change, even though your invalid date still shows in the form control.