Knockout.js validation - javascript

I'm new to Knockout.js tech where I Googled many site to resolve my situation where I couldn't find a better option.
How to validate a date using Knockout.js? Where in my case if the user typed the date in a wrong format say for e.g if the valid date format is dd-M-yyyy but the user is typing M-dd-yyyy it should automatically convert it to a valid date format.
My sample code is this,
self.dateOfBirth = ko.observable(0).extend({
required: { message: 'Date of Birth is required', params: true },
date: { format: 'dd-M-YYYY' ,
message: 'Not a valid date format',params:true
}
My HTML design is this,
<input class="form-control" id="dateOfBirth" autocomplete="off" placeholder="Date of Birth" type="text" data-bind="value: dateOfBirth, format:'dd-M-YYYY', valueUpdate: 'afterkeydown'">

Take a look at "Writable computed observables" example 3 and example 4 on the official Knockout documentation site.
Example:
this.formattedDate = ko.pureComputed({
read: function () {
return this.date();
},
write: function (value) {
// convert date to dd-M-YYYY, then write the
// raw data back to the underlying "date" observable
value = convertDate(value); // add your own conversion routine
this.date(value); // write to underlying storage
},
owner: this
});
Also consider using the textInput binding, instead of value combined with valueUpdate, for consistent cross-browser handling.

Consider using Knockout event and capture its change event and then use moment.js library to convert it into any date format you like.
In HTML:
<input class="form-control" id="dateOfBirth" autocomplete="off" placeholder="Date of
Birth" type="text" data-bind="value: dateOfBirth, event: { change: dataChanged},
valueUpdate: 'afterkeydown'">
In javascript:
Inside your viewModel
//this function will be called when the date will be changed
self.dataChanged = function(){
//using moment .js here change the format to dd-M-YYYY as desired
var validFormat = moment(self.dateOfBirth()).format('dd-M-yyyy');
self.dateOfBirth(validFormat);
}
for further details check moment.js liberary

Related

Bootstrap Datepicker With Daterange Not Saving Value as the Specified Format

I have a booking form that requires two dates, so I'm using the built in option that Bootstrap datepicker has (it consists on calling the datepicker function on the father element that contains the inputs), to show the daterange selected, this is my HTML:
<div class="grupo vip-fechas input-daterange">
<div class="barra verde"> <span>¿Cuándo llegas?</span></div>
<input type="text" class="input calendario" id="entrada_input" name="entrada_input" placeholder="Selecciona una fecha">
<input type="hidden" id="fecha_inicio" name="fecha_inicio">
<div class="barra verde"> <span>¿Cuándo te vas?</span></div>
<input type="text" class="input calendario" id="salida_input" name="salida_input" placeholder="Selecciona una fecha">
<input type="hidden" id="fecha_fin" name="fecha_fin">
</div>
This is my Javascript code:
$(document).ready(function(){
iniciarFechas();
});
function iniciarFechas(){
var date = new Date();
var today = new Date(date.getFullYear(), date.getMonth(), date.getDate());
var date_hidden;
$('.vip-fechas.input-daterange').datepicker({
weekStart: 1,
maxViewMode: 1,
language: "es",
startDate: today,
disableTouchKeyboard: true,
format: {
toDisplay: function(date, format, language) {
var fecha = moment(date).add(1,"day");
date_hidden = fecha;
return fecha.format("dddd DD [de] MMMM, YYYY");
},
toValue: function(date, format, language) {
var fecha = moment(date).add(1,"day");
return moment(fecha).format("DD/MM/YY");
//return moment(date, ["DD.MM.YYYY", "DDMMYYYY"]).toDate();
}
},
}).on("changeDate", function(e){
var fecha_formateada = moment(date_hidden).format("DD/MM/YY");
$(this).next().val(fecha_formateada);
});
}
The daterange works correctly but I want to store the formatted date inside the hidden inputs, as you can see, the format that I want is this: ...format("DD/MM/YY"); but what I get is the display format: format("dddd DD [de] MMMM, YYYY"), also I noticed that $(this) value within this line: $(this).next().val(fecha_formateada); refers to the container div, and not the input that has changed value, so how can I save the date as I want inside the hidden inputs?
I'm not sure what your problem is but by looking at your code I can only guess that you might be in the middle of a race condition.
You're setting the date_hidden variable in Datepicker.toDisplay and then reading from it in the changeDate custom event.
Put a debugger or a console log in both callbacks to make sure you're not in the middle of a race condition.
As for setting the formatted value in the input fields, well I can see in your HTML code that you have selectors that you can use, like the hidden field's ID for example.
Another thing I'd suggest is, instead of setting and reading the date_hidden field in those different callbacks, just call $('#elementID').datepicker('getDate') in the changeDate event handler and do all the transformations you need there, then extract that code and put it in a separate function.

How to restrict user to enter date manually in date field

I am working on an application in which i want to restrict user to manually enter the date in the type=date field in html page.
I want to restrict the user to select the date only from the calender display which is MM/DD/YYYY.
Below is the code in html page :
<input type="date" name="bankTrans" ng-model="orderAstro.paymentDate"
class="form-control" id="bankTrans"
ng-disabled="isDisabled" required />
Also attaching the image for error clarity :
Image for error clarity
use following line of code to restrict manual date field entry using jquery.
$("input[type='date']").keydown(function (event) { event.preventDefault(); });
Edit 1:
Your question makes sense.
The best way to work with a date is to disable manual entry and allow changes only using the Date Picker.
Add a 'readonly' attribute to the input field:
<input type="date" readonly name="bankTrans"
ng-model="orderAstro.paymentDate" class="form-control"
id="bankTrans" ng-disabled="isDisabled" required />
Do you want the code for above Angular js file and HTML as well or this much is fine.
Edit 2:
Disabling the manual Entry of Date and allowing only through Date Picker.
HTML code:
<input type="text" readonly class="form-control" datepicker-popup="{{clCtrl.format}}"
ng-model="clCtrl.QualityExpirationDate" is-open="clCtrl.openedQualityDate"
min-date="clCtrl.minDate" datepicker-options="clCtrl.dateOptions"
ng-required="true" close-on-date-selection="true"
show-button-bar="false" />
js file:
$scope.$watch('dt', function(val) {
$scope.isValidDate = isNaN(new Date(val).getTime());
});
self.dateOptions = {
formatYear: 'yy',
startingDay: 1
};
self.formats = ['MM-dd-yyyy', 'MM/dd/yyyy', 'MM.dd.yyyy', 'shortDate'];
self.format = self.formats[0];
self.openQualityDate = function ($event) {
$event.preventDefault();
$event.stopPropagation();
self.openedQualityDate = true;
};
self.toggleMin = function () {
self.minDate = self.minDate ? null : new Date();
};
self.toggleMin();
self.clear = function () {
self.QualityExpirationDate = null;
};
Please ignore this, is not solving the issue, as intended.
This might help: https://jsdaddy.github.io/ngx-mask-page/main#prefix
<input mask="00/00/0000">
what worked for me!
added the following attributes to my date type input tags.
<input type="date" name="dob" "minlength": "10", "maxlength": "10", class="form-control" />

How to restrict date format in date field

I'm trying to implement a function that will bring up an alert box when a date in the wrong format is entered and the submit button is pressed. I have six date fields in my form.
I can't seem to find regex examples that show me how to implement the function in my field inputs only how to do the function itself. I wanted to restrict it to YYYY-MM-DD. Posting here is the last resort for me, I have looked for a long time to no avail. Please can someone help?
function validate_date() {
var date_regex = /^(0[1-9]|1[0-2])\/(0[1-9]|1\d|2\d|3[01])\/(19|20)\d{2}$/ ;
if(!(date_regex.test(testDate)))
{
alert('Wrong format!');
return false;
}
}
<input type="text" class="form-control" id="empexpiry" style="width:350px;" placeholder="Nothing on File" name="empexpiry" value=""
If I was you I would use some plugin. There are good vanilla and jQuery plugins to validate forms (e.g. Vanilla, jQuery).
But if you wanna do it by yourself:
Listen to the submit event of the form and validate all your entries using regex
The function to validate could be something like this
function isDateValid (dateStr) {
let isValid = dateStr.match(/[0-9]{4}-[0-9]{2}-[0-9]{2}/)
if (!isValid) return false
const dateObj = new Date(dateStr);
isValid = dateObj != 'Invalid Date'
return isValid
}
And your function to listen the submit could be something like this:
function validateForm (e) {
const input1 = document.getElementById("input1").text
if (!isDateValid(input1)) {
alert('invalid')
e.preventDefault()
return false
}
/* And so on */
}
I found out that the HTML5 pattern attribute was all that was required. Simple!
<input id="date" type="text" pattern="\d{4}-\d{1,2}-\d{1,2}" oninvalid="setCustomValidity('Please make sure the date follows this format: YYYY-MM-DD')" required="required"/>

Ionic / Angular date input set programatically using moment

I'm trying to set the value of a "date" input but im getting this error message :
Error: [ngModel:datefmt] Expected `03/27/2012` to be a date
I was under the impression that the correct format was MM/DD/YYYY? ive also tried DD/MM/YYYY.
I'm using moment.js to format then setting the value of the textbox.
<label class="item item-input item-stacked-label">
<span class="input-label">Date Entered :</span>
<input type="date" placeholder="Date Entered" value="" ng-model="entered">
</label>
controller :
$scope.entered = moment($scope.entered).format("MM/DD/YYYY");
There is a library called angular-moment, where you can use a variety of filters.
Check it out: https://github.com/urish/angular-moment
You could do this:
dateobj = $scope.entered
var tempobj = {
year: dateobj.getFullYear(),
month: dateobj.getMonth(),
day: dateobj.getDate()
}
var momentobj = moment(tempobj).format('format it the way you want to');

How can I compute two dates using Knockout JS?

I'm trying to use Knockout computed to concatenate two dates as I change them.
From the examples, it seems I do not need to use valueUpdate: 'input'. But nothing is happening when I change the dates (using Bootstrap datepicker). Any ideas to what I'm missing?
Here's my fiddle.
And my code:
<div class="input-append date">
<input type="text" data-bind="value: fromDate, valueUpdate: 'input'" class="date from-date" />
<span class="add-on">to</span>
<input type="text" data-bind="value: toDate, valueUpdate: 'input'" class="date to-date" />
</div>
Dato: <span class="date" data-bind="date"></span>
function dateModel() {
var self = this;
self.fromDate = ko.observable('12.09.2014');
self.toDate = ko.observable();
self.validPeriod = ko.computed(function () {
return self.fromDate + " - " + self.toDate;
}, self);
}
ko.applyBindings(dateModel());
Because your date picker objects are of type koObservable, you need to treat the objects as functions, so your validPeriod function should look like:
self.validPeriod = ko.computed(function () {
return self.fromDate() + " - " + self.toDate();
}, self);
The Knockout.js documentation for observables states:
To read the observable’s current value, just call the observable with
no parameters. In this example, myViewModel.personName() will return
'Bob', and myViewModel.personAge() will return 123.
Then i would suggest using the text data binding for the date span element to call the calculation function:
<span class="date" data-bind="text: validPeriod"></span>
Thanks to the comment of #Buck Doyle and some research, it seems that Knockout.js needs special handling regarding datetime picker controls, as showed in this SO post - jQuery UI datetimepicker and Knockout.js - one possible solution to your problem would be to implement the custom datetime picker handling for KOjs.
This page - custom bindings with KOjs explains very good (with example) how to bind the datetime picker control.

Categories

Resources