datetimepicker bootstrap minDate and maxDate in observable knockout - javascript

I am using the plugin bootstrap-datetimepicker with knockout js. I've done a handler to dynamically manage and MaxDate MinDate, as I show below:
ko.bindingHandlers.dateTimePicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().dateTimePickerOptions || {};
$(element).datetimepicker(options);
//when a user changes the date, update the view model
ko.utils.registerEventHandler(element, "dp.change", function (event) {
var value = valueAccessor();
if (ko.isObservable(value)) {
if (event.date && event.date != null && !(event.date instanceof Date)) {
value(event.date.toDate());
} else {
//value(event.date);
value(undefined);
}
}
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
var picker = $(element).data("DateTimePicker");
if (picker) {
picker.destroy();
}
});
},
update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
var picker = $(element).data("DateTimePicker");
//when the view model is updated, update the widget
if (picker) {
//Usamos moment para convertir a fecha ya que utiliza este plugin adicional datetimepicker
var koDate = moment(ko.utils.unwrapObservable(valueAccessor()) || '');
if (koDate.isValid()) picker.date(koDate.toDate() || null);
}
}
};
ko.bindingHandlers.minDate = {
update: function (element, valueAccessor) {
var value = moment(ko.utils.unwrapObservable(valueAccessor()) || ''),
picker = $(element).data("DateTimePicker");
if (value.isValid() && picker) {
picker.minDate(value.toDate());
}
}
};
ko.bindingHandlers.maxDate = {
update: function (element, valueAccessor) {
var value = moment(ko.utils.unwrapObservable(valueAccessor()) || ''),
picker = $(element).data("DateTimePicker");
if (value.isValid() && picker) {
picker.maxDate(value.toDate());
}
}
};
I use it as follows:
<div class="input-group" data-bind="dateTimePicker: NuevaTarea.FechaInicio, dateTimePickerOptions: { format: 'L', showClear: true }, minDate: NuevaTarea.minDate, maxDate: NuevaTarea.maxDate">
<input type="text" class="form-control" />
<div class="input-group-addon">
<i class="fa fa-calendar"></i>
</div>
</div>
The problem is when change the NuevaTarea.minDate and NuevaTarea.maxDate, the date of MaxDate is assigned to NuevaTarea.FechaInicio.
Someone could help me create an observable MaxDate MinDate and properly functioning? No I'm doing wrong.
The version of plugin is 4.15.35.
https://github.com/Eonasdan/bootstrap-datetimepicker

ko.bindingHandlers.dateTimePicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().dateTimePickerOptions || {};
$(element).datetimepicker(options);
//when a user changes the date, update the view model
ko.utils.registerEventHandler(element, "dp.change", function (event) {
var value = valueAccessor();
if (ko.isObservable(value)) {
if (event.date && event.date != null && !(event.date instanceof Date)) {
value(event.date.toDate());
} else {
//value(event.date);
value(undefined);
}
}
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
var picker = $(element).data("DateTimePicker");
if (picker) {
picker.destroy();
}
});
},
update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
var picker = $(element).data("DateTimePicker");
//when the view model is updated, update the widget
if (picker) {
//Usamos moment para convertir a fecha ya que utiliza este plugin adicional datetimepicker
var koDate = moment(ko.utils.unwrapObservable(valueAccessor()) || '');
if (koDate.isValid()) picker.date(koDate.toDate() || null);
}
}
};
ko.bindingHandlers.minDate = {
update: function (element, valueAccessor) {
var value = moment(ko.utils.unwrapObservable(valueAccessor()) || ''),
picker = $(element).data("DateTimePicker");
if (value.isValid() && picker) {
picker.minDate(value.toDate());
}
}
};
ko.bindingHandlers.maxDate = {
update: function (element, valueAccessor) {
var value = moment(ko.utils.unwrapObservable(valueAccessor()) || ''),
picker = $(element).data("DateTimePicker");
if (value.isValid() && picker) {
picker.maxDate(value.toDate());
}
}
};
function ViewModel() {
var self = this;
self.NuevaTarea = {
FechaInicio: ko.observable(),
FechaFin: ko.observable(),
minDate: ko.observable(),
maxDate: ko.observable()
};
self.NuevaTarea.minDate(new Date()) ;
//Not is working apply value null, help here!! I Like that this field is empty on start
self.NuevaTarea.FechaInicio(null);
}
ko.applyBindings(new ViewModel());
body{height:300px; padding:20px;}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.15.35/css/bootstrap-datetimepicker.min.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.15.35/js/bootstrap-datetimepicker.min.js"></script>
<div class="form-group">
<label class="control-label">Min Date:</label>
<div class="input-group" data-bind="dateTimePicker: NuevaTarea.minDate, dateTimePickerOptions: { format: 'L', showClear: true }">
<input type="text" class="form-control" />
<div class="input-group-addon">
<i class="glyphicon glyphicon-calendar"></i>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label">Fecha Inicio:</label>
<div class="input-group" data-bind="dateTimePicker: NuevaTarea.FechaInicio, dateTimePickerOptions: { format: 'L', showClear: true }, minDate: NuevaTarea.minDate, maxDate: NuevaTarea.maxDate">
<input type="text" class="form-control" />
<div class="input-group-addon">
<i class="glyphicon glyphicon-calendar"></i>
</div>
</div>
</div>

Thanks for your help but I already solved only just set, useCurrent: false options.
<div class="input-group" data-bind="dateTimePicker: NuevaTarea.FechaInicio, dateTimePickerOptions: { format: 'L', showClear: true, useCurrent: false }, minDate: NuevaTarea.minDate, maxDate: NuevaTarea.maxDate">
<input type="text" class="form-control" />
<div class="input-group-addon">
<i class="fa fa-calendar"></i>
</div>
</div>

Related

Failed to set the 'value' property on 'HTMLInputElement':

If I upload a PDF or a picture to the form, I get the following error message when changing to another form field:
The upload function is done using the following JavaScript:
;(function($,window) {
$.plugin('OnacyUpload', {
defaults: {
fileUpload: '#register_license_upload',
fileText: '.register-upload-file-text',
registerContent: '.register--content.registration-upload-finished',
registerLogin: '.register--login',
sidebar: 'aside.sidebar-main',
breadcrumb: 'nav.content--breadcrumb'
},
init: function() {
var me = this;
me._on(me.opts.fileUpload, 'change', $.proxy(me.onUploadChange, me));
me._on(me.opts.fileText, 'click', $.proxy(me.fileTextClicked, me));
if ( $(me.opts.registerContent).length ) {
$(me.opts.registerLogin).remove();
$(me.opts.sidebar).remove();
$(me.opts.breadcrumb).remove();
}
},
fileTextClicked: function() {
$(me.opts.fileUpload).trigger('click');
},
onUploadChange: function(event) {
var me = this,
$target = $(event.target),
$fileText = $(me.opts.fileText),
value = $target.val();
if ( typeof value !== 'string' || value === '' ) {
$fileText.html($fileText.attr('data-no-file-text'));
}
else {
var list = value.replace(/\\/g, '/').split('/');
$fileText.html(list[list.length-1]);
}
}
});
window.StateManager.addPlugin('body', 'OnacyUpload');
Here is the HTML Part:
<div class="panel--body is--wide"> <input type="file" id="register_license_upload" name="register_license_upload" accept="image/png, image/jpeg, application/pdf"> <label for="register_license_upload" class="btn is--secondary"> Datei aussuchen </label> <span class="register-upload-file-text" data-no-file-text="Datei wählen"> Datei wählen </span> </div>

Login with enter key pressed knockout js

I have been trying to get my login page to work once I pressed the enter key, but it doesn't work. Help anyone?
Here is my codes:
Javascript/ viewModel:
ko.bindingHandlers.enterkey = {
init: function (element, valueAccessor, allBindings, viewModel) {
var callback = valueAccessor();
$(element).keypress(function (event) {
var keyCode = (event.which ? event.which : event.keyCode);
if (keyCode === 13) {
callback.call(viewModel);
return false;
}
return true;
});
}
};
Mobile.Login = function (params) {
var viewModel = {
dxPasswordTB: {
value: ko.observable(""),
showClearButton: true,
placeholder: ko.observable("PASSWORD"),
mode: 'password'
},
validateAndSubmit: function (params) {
var result = params.validationGroup.validate();
...
},
};
return viewModel;
};
View/ HTML:
<div class="row">
<div class="col-sm-12 col-xs-12">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon"><i class="icon-password"></i></span>
<div class="form-control">
<div data-bind="dxTextBox: dxPasswordTB, dxValidator: PasswordVR, valueUpdate: 'afterkeydown', enterkey: validateAndSubmit""></div>
</div>
</div>
</div>
</div>
</div>
Any idea what went wrong here? If you do, please post your suggestions here, thanks!
I managed to resolve this by using onEnterKeyin dxPasswordTB from devExpress. Also, I changed params.validationGroup.validate(); to DevExpress.validationEngine.validateGroup() and the value was finally defined.

bootstrap-datepicker (range) - AngularJS Directive

I'm trying to make use of the bootstrap-datepicker.
I have an existing AngularJS directive, but when setting the initial value, it does not update when making use of a date range.
HTML
<div class="input-group input-daterange" id="fromToDate" calendar ng-model="vm.fromToDate">
<input type="text" class="form-control input-sm" required ng-model="vm.bookingFromDate">
<span class="input-group-addon">to</span>
<input type="text" class="form-control input-sm" required ng-model="vm.bookingToDate">
</div>
Directive
// this directive updates the value, once it has been selected, but not when the initial value has been set**
function calendar() {
return {
require: 'ngModel',
link: function($scope, el, attr, ngModel) {
$(el)
.datepicker({
autoclose: true,
todayHighlight: true,
todayBtn: 'linked',
onSelect: function(dateText) {
$scope.$apply(function() {
ngModel.$setViewValue(dateText);
});
}
});
}
};
};
Then, I tried the following directive (found here), but this doesn't work either for a date range - instead:
function calendar() {
return {
require: '?ngModel',
restrict: 'A',
link: function ($scope, element, attrs, controller) {
var updateModel, onblur;
if (controller != null) {
updateModel = function (event) {
element.datepicker('hide');
element.blur();
};
onblur = function () {
var date = element.val();
return $scope.$apply(function () {
return controller.$setViewValue(date);
});
};
controller.$render = function() {
var date = controller.$viewValue;
element.datepicker().data().datepicker.date = date.from.toDate();
element.datepicker('setValue');
element.datepicker('update');
return controller.$viewValue;
};
}
return attrs.$observe('bdatepicker', function (value) {
var options = {
format: "yyyy/mm/dd",
todayBtn: "linked",
autoclose: true,
todayHighlight: true
};
return element.datepicker(options).on('changeDate', updateModel).on('blur', onblur);
});
}
};
};
Any assistance would be appreciated!
Thanks!
[Update]
CodePen to illustrate the issue:
<p data-height="322" data-theme-id="dark" data-slug-hash="BLkagb" data-default-tab="js,result" data-user="Programm3r" data-embed-version="2" class="codepen">See the Pen Bootstrap-Datepicker (Range) AngularJS by Richard (#Programm3r) on CodePen.</p>
<script async src="//assets.codepen.io/assets/embed/ei.js"></script>
You could use the following library to solve the issue. datepicker
Edit: to resolve disappearance of date.
<input type="text" class="form-control input-sm" ng-model="vm.bookingFromDate" id="fromDate">
<span class="input-group-addon">to </span>
<input type="text" class="form-control input-sm" ng-model="vm.bookingToDate" id="toDate">
in controller
$('#fromDate').val(vm.bookingFromDate);
$('#toDate').val(vm.bookingToDate);

How to set datepicker minDate?

I have a directive date-picker.js and view as selectDate.html. I want to set minDate for the date picker when the value of another datepicker changes. How to achieve that?
.directive('selectDate', ['moment', function(moment) {
return {
restrict: 'E',
require:'^ngModel',
templateUrl: 'views/selectDate.html',
replace: true,
scope: {
ngModel: '='
},
link: function($scope, element, attrs) {
$scope.date = $scope.ngModel;
$scope.dateOptions = {
startingDay: 1,
showWeeks: false
};
$scope.dateStatus = {
opened: false
};
$scope.openDatePopup = function() {
$scope.dateStatus.opened = true;
};
$scope.$watch('date', function (newValue, oldValue) {
if (newValue !== oldValue) {
var date = moment(newValue);
$scope.ngModel = date.format('YYYY-MM-DD');
}
});
}
};
selectDate.html
<span class="select-date">
<input type="text" readonly="readonly" datepicker-popup="dd.MM.yyyy" datepicker-options="{startingDay: 1, showWeeks: true}" ng-model="date" show-button-bar="false" current-text="Heute" close-text="Schließen" is- open="dateStatus.opened" min-date="'2014-01-01'" class="form-control" required="required" ng-click="openDatePopup()">
</span>
I am using it like below:
From <select-date ng-model="fromDate"></select-date>
To <select-date ng-model="toDate"></select-date>
I want to set minDate of toDate to fromDate value.
Well you can user ui-bootstrap directive which is lot easier,below is the code
$scope.dateOptions = {
formatYear: 'yyyy',
startingDay: 1
};
$scope.opened = true;
$scope.minDate= new Date();
var maxDate = new Date();
maxDate.setFullYear (maxDate.getFullYear() + 2);//enable for 2 future years..
$scope.maxDate= maxDate;
Your HTML will look like this
<input type="text" class="form-control selection-box"
id="datepicker"
datepicker-popup="{{dateFormat}}"
ng-model="selectedDate" is-open="opened"
ng-class="{'date-changed':colorChange[$parent.$parent.$index +'-'+ $parent.$index]}"
min-date="minDate" max-date="maxDate"
datepicker-options="dateOptions" readonly="readonly"
ng-change="changeDate()"
close-text="Close" ng-required="true" />
To answer OP's question you can have following code changes.
From <select-date ng-model="fromDate" min-date="fromMinDate"></select-date>
To <select-date ng-model="toDate" min-date="toMinDate"></select-date>
<span class="select-date">
<input type="text" readonly="readonly" datepicker-popup="dd.MM.yyyy" datepicker-options="{startingDay: 1, showWeeks: true}" ng-model="date" show-button-bar="false" current-text="Heute" close-text="Schließen" is- open="dateStatus.opened" min-date="setMinDate" class="form-control" required="required" ng-click="openDatePopup()">
</span>
Below are changes in your directive.
.directive('selectDate', ['moment', function(moment) {
return {
restrict: 'E',
require:'^ngModel',
templateUrl: 'views/selectDate.html',
replace: true,
scope: {
ngModel: '='
minDate: '#'//which date input we are changing...
},
link: function($scope, element, attrs) {
$scope.date = $scope.ngModel;
$scope.selectedDateType = $scope.minDate=='fromMinDate'?'From':'To';
$scope.dateOptions = {
startingDay: 1,
showWeeks: false
};
$scope.dateStatus = {
opened: false
};
$scope.openDatePopup = function() {
$scope.dateStatus.opened = true;
$scope.setMinDate = new Date();//for From date..
};
$scope.$watch('date', function (newValue, oldValue) {
if (newValue !== oldValue) {
var date = moment(newValue);
$scope.ngModel = date.format('YYYY-MM-DD');
if($scope.selectedDateType=='From'){
$scope.setMinDate = $scope.fromDate;//for To date
}
}
});
}
};

How to get Knockout dialog to update

I got this dialog popup that I want to update with a selected Text.
<div data-bind="with: SelectedText">
<div id="dialog" data-bind="dialog: {'autoOpen': false, 'title': textbatchTitle }, dialogVisible: $root.isMetadataDialogOpen">
<div class="metadata">
<label for="textbatchTitle">Title:</label> <span class="rotten">Why isen´t this updated with SelectText after pushing "Add New Text"?"</span>
<input type="text" name="textbatchTitle" data-bind="value: textbatchTitle, valueUpdate: 'afterkeydown'" />
</div>
</div>
</div>
It seems the dialog does´t respond to the "with"-binding?
This is my custom binding:
ko.bindingHandlers.dialog = {
init: function (element, valueAccessor, allBindingsAccessor) {
var options = ko.utils.unwrapObservable(valueAccessor()) || {};
//do in a setTimeout, so the applyBindings doesn't bind twice from element being copied and moved to bottom
setTimeout(function () {
options.close = function () {
allBindingsAccessor().dialogVisible(false);
};
$(element).dialog(ko.toJS(options));
}, 0);
//handle disposal (not strictly necessary in this scenario)
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).dialog("destroy");
});
},
update: function (element, valueAccessor, allBindingsAccessor) {
var shouldBeOpen = ko.utils.unwrapObservable(allBindingsAccessor().dialogVisible),
$el = $(element),
dialog = $el.data("uiDialog") || $el.data("dialog"),
options = valueAccessor();
//don't call dialog methods before initilization
if (dialog) {
$el.dialog(shouldBeOpen ? "open" : "close");
for (var key in options) {
if (ko.isObservable(options[key])) {
$el.dialog("option", key, options[key]());
}
}
}
}
};
What is wrong with this?
http://jsfiddle.net/qFjRW/
You didn't include jquery ui as an external source:
Uncaught TypeError: Object [object Object] has no method 'dialog'
See http://jsfiddle.net/FXTHn
EDIT:
Since you're using the with: SelectedText outside of the dialog, it won't call update when SelectedText changes. Try placing it inside:
<div id="dialog" data-bind="dialog: {'autoOpen': false, 'title': SelectedText().textbatchTitle }, dialogVisible: $root.isMetadataDialogOpen">
<div data-bind="with: SelectedText">
<div class="metadata">
<label for="textbatchTitle">Title:</label> <span class="rotten">Why isen´t this updated with SelectText after pushing "Add New Text"?"</span>
<input type="text" name="textbatchTitle" data-bind="value: textbatchTitle, valueUpdate: 'afterkeydown'" />
</div>
</div>
</div>
http://jsfiddle.net/FXTHn/1/

Categories