AngularJS datepicker ui-date bad updates - angularjs

The two-way data-binding appears to be causing bad updates to the field. Clicking on the field raises the datepicker fine, but if you attempt to edit the field by directly typing in a date, it doesn't quite work.
Here's the fiddle demonstrating the issue: http://jsfiddle.net/vSNJF/
<input type="text" ng-model="name" ui-date-format='m/d/yy' ui-date>
Compare the keyboard-editing under Angular to the standard jquery UI date picker behavior here: http://jqueryui.com/datepicker/
How can I make ui-date delay updating the model until after the interactive calendar is dismissed?

You've got quite a big directive there, I am not sure if anyone is going to go through the whole code to find what is causing the problem. To help I will leave a simpler datepicker directive that behaves exactly like Jquery UI's but without all the features you have implemented in yours, maybe if your start from this point and go adding features it would be easier to debug the problem.
The directive is:
directive('datepicker', function() {
return {
restrict: 'A',
require : 'ngModel',
link : function (scope, element, attrs, ngModelCtrl) {
$(function(){
element.datepicker({
dateFormat:'dd/mm/yy',
onSelect:function (date) {
ngModelCtrl.$setViewValue(date);
scope.$apply();
}
});
});
}
}
});
Here is a Plunker and a blog post about it.

Related

How to set the cursor focus on input field?

I would like to set the cursor focus on an input field as soon as the form (directive) is shown. I tried adding the following code to my link function:
link: function (scope, element, attrs) {
element('input[name=headline]').focus();
}
But it does not work. I also tried the following variants:
element.find('input[name=headline]').focus();
element.querySelector('input[name=headline]').focus();
I did not find any useful information on the Web. md-autofocus seems to have nothing to do with what I am trying to achieve.
Option 1
HTML autofocus
Option 2
Try playing with ng-focus from angular.
Update
My bad, ng-focus, from the doc:
Specify custom behavior on focus event.
So ng-focus is not what you need to use. keep on autofocus.
Final solution with ng-if
https://plnkr.co/edit/sb29aGHGtdFQ7fiLdbtN?p=preview
Create a directive that will apply the focus for you.
myApp.directive('yourAutofocus', ['$timeout', function($timeout) {
return {
restrict: 'A',
link : function($scope, $element) {
$element[0].focus();
}
}
}]);
Try like this
ng-if="showMe" ng-focus="true && showMe" or ng-focus="focudMe=true; showMe=true"

Using bootstrap-datepicker with angular xeditable

I have a table and I would like to add in-line editing to that table. I started with ng-grid, however, I decided that while it worked well, I was spending too much time trying to fix the styling so that it would match the overall theme of my website. I started fresh and am now using a plain old html table with angularjs behind the scenes for its awesome two-way-data-binding property.
Everything has been going smoothly except for the fact that I am stuck on trying to get inline editing to work with bootstrap-datepicker: http://www.eyecon.ro/bootstrap-datepicker/?utm_source=twitterfeed&utm_medium=twitter. The reason I am using this datepicker over the ui-bootstrap datepicker that xeditable says you should use is because it does not look or feel right in my website. Here is what the ui-bootstrap datepicker looks like http://jsfiddle.net/NfPcH/23/. I like the simple and plain look of the bootstrap datepicker.
Here is a plunker of a table with xeditable and date fields to try and edit PLUNKER
Using bootstrap-datepicker as an input field works fine, a custom directive is used to properly update the model:
editablegrid.directive('datepicker', function() {
return {
restrict : 'A',
require : 'ngModel',
link : function(scope, element, attrs, ngModelCtrl) {
$(function() {
var dp = $(element).datepicker({
format : 'MM dd, yyyy'
});
dp.on('changeDate', function(e) {
ngModelCtrl.$setViewValue(e.format('MM dd, yyyy'));
scope.$apply();
});
});
}
}
I changed the xeditable source code to use bootstrap-datepicker (see lines 78-84 of xeditable.js)
/*
The New directive I've made for xeditable to use with the bootstrap-datepicker
*/
angular.module('xeditable').directive('editableBsdateNew', ['editableDirectiveFactory',
function(editableDirectiveFactory) {
return editableDirectiveFactory({
directiveName: 'editableBsdateNew',
inputTpl: '<input type="text" class="form-control form-control-inline input-sm" datepicker>'
});
}]);
, however the problem lies somewhere with xeditable and how it updates the model of the selected row.
xeditable works perfectly for editing text and dropdowns in-line, trying to integrate with bootstrap-datepicker is proving to be difficult.
If there is some other way to use in-line editing with bootstrap-datepicker, I would not be opposed to trying it out. I was thinking that if this didn't work, maybe something with ng-show and ng-hide might do the trick.
1 > Make sure you install two libraries
- angular-xeditable
- angular-bootstrap-datepicker
2> Create new directive
/* The New directive I've made for xeditable to use with the
bootstrap-datepicker
*/
angular.module('xeditable').directive('editableBootstrapDatepicker', ['editableDirectiveFactory', function(editableDirectiveFactory) {
return editableDirectiveFactory({
directiveName: 'editableBsdateNew',
inputTpl: '<span ng-datepicker ng-options="datepickerOptions"></span>'
}); } ]);
3> In HTML put something like:
<span editable-bootstrap-datepicker="yourDateModel" onbeforesave="validateBeforeSaveDate($data)">Date ...</span>
Try this:
dp.on('changeDate', function(e) {
ngModelCtrl.$setViewValue(e.format('MM dd, yyyy'));
scope.$apply();
scope.row.dueDate = e.format('MM dd, yyyy'); //<--- new line
});

Angular-strap datepicker doesn't update existing model value

I am using angular-strap datepicker from http://mgcrea.github.io/angular-strap/##datepickers for my angularjs SPA project. when editing an existing record using ngModel two way binding, Angular doesn't detect the date field change and even if I force the form to save by updating another non date field, the new date is not updated in backend. Here is the related part in my html file:
<input name="DecisionDatePicker" id="ddpID" type="text" class="form-control input-medium" tabindex="14" placeholder="{{vm.format}}"
data-date-format="MM-dd-yyyy"
data-ng-model="vm.formData.dateDecision"
data-ng-required="vm.decisionDateRequired"
bs-datepicker />
I do not do anything special in my js file. I am using breezejs for my data handling and it is working fine for other fields.
what am I doing wrong? Any help is appreciated.
I've had this same problem and I solved with a custom directive that updates the model when the bs-datepicker dispatches a blur event:
angular.module('moduleName').directive('updateModelOnBlur',
['$parse', function($parse) {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, elm, attrs) {
elm.bind("blur", function (event) {
scope.$apply(function () {
var model = $parse(attrs.ngModel);
model.assign( scope, elm.context.value );
});
});
}
};
}]
);
I know this is just a hack, and not a final solution for the problem. But, if you are stuck and want to keep going, sometimes a hack might be useful.
You can also include $filter service in the directive if you want to manipulate date format before updating model. ;)

AngularJs dynamic form generation with validation

I am trying to generate form dynamically and use validation at the same time. The problem that I have now is that the input attribute name='{{key}}' is not interpolated by the validation.
<div ng-repeat="options in formObject">
<input type='radio' ng-model='ranodm' name='{{key}}'>
</div>
I know that I should use ng-form if I want a dynamic form, however I am having hard time to understand it. I am adding my simple plnkr example of what I am trying to achieve. It would be nice if someone would show how to solve this using ng-form or other method.
http://plnkr.co/edit/faG89bmu18nNNODVRV3x
I found an answer from reading through this SO post: Dynamic validation and name in a form with AngularJS
I ended up using the dynamicName directive to work around this problem so I could use a UUID of as the name of the field. Here's a plnkr and the directive I used. I can't take credit for the directive, I found it on that other post.
http://plnkr.co/edit/RFrRXp2kWkP1Mefwl3Kn?p=info
myApp.directive('dynamicName', function($compile, $parse) {
return {
restrict: 'A',
terminal: true,
priority: 100000,
link: function(scope, elem) {
var name = $parse(elem.attr('dynamic-name'))(scope);
elem.removeAttr('dynamic-name');
elem.attr('name', name);
$compile(elem)(scope);
}
};
});
Go through following link this will help.
http://www.benlesh.com/2013/03/angular-js-validating-form-elements-in.html

Angular (directive newbie): How to add date time-picker to ngModel so that it can be validated?

I am very new to Angular and have a specific use case in mind
I have a form which has two fields - Name and datetime.
The name is ng-model but datetime is not since it is not part of Angular and is a jquery component
What I want to do?
Here is the plunker = http://plnkr.co/edit/wGrvXAFmPGoYSwh9GfxH?p=preview
a.) I want to associate date to ngModel like ngModel="transaction.date"
b.) validate it as required using Angular way
Something which will look like (much like Angular)
<input type="text" name="transactionDate" ng-model="transaction.date" data-date-format="yyyy-mm-dd hh:ii" required>
Why?
a.) To to things Angular way
b.) It makes model more consistent to test, validate
I asked this question on Stackoverflow and it was recommended to use custom directive, can someone give me direction with example how to do it?
Please guide me further since I am not able to validate it currently
Thank you very much
Based on Ketan's answer, I had to write a new directive and associate the value form jQuery to ng-model, which then is validated with form. The directive looks like
app.directive('dateTime', function(){
return {
restrict: 'A',
require: '?ngModel',
link: function(scope, element, attrs, ngModel){
if (!ngModel) {
console.log('no model, returning');
return;
}
element.bind('blur keyup change', function() {
console.log('datetime changed: ', $('.form_datetime input').val());
scope.$apply(read);
});
read();
function read() {
ngModel.$setViewValue(element.val());
}
}
}
});
The plunker can be found here
Assuming you know how to write directives, you need to use the NgModelController inside your directive and use the $setViewValue(value) method. (See example the below page).
http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController
This has to be called from your custom Datepicker event which triggers when the user completes the selection.

Resources