Angular-Ui Bootstrap DatePicker Open on focus - angularjs

Though this may seem like a simple question, I can't find anywhere a solution.
Simple as this:
<input type="text" datepicker-popup>
I want that when the cursor enters, the calendar popup automatically shows up, like jquery-ui datepicker. Now I have to either provide a button or Alt-down, both unfriendly to me.
There is a is-open attribute but I dont want to complicate things putting variables in the scope for something that probably should already be available as a configuration? :D.
Thanks

EDIT:
I finally found the solution. It's a little tricky but it works. Here is the directive:
app.directive("autoOpen", ["$parse", function($parse) {
return {
link: function(scope, iElement, iAttrs) {
var isolatedScope = iElement.isolateScope();
iElement.on("focus", function() {
isolatedScope.$apply(function() {
$parse("isOpen").assign(isolatedScope, "true");
});
});
// Remove DOM Event Listener when $destroy lifecycle event is fired
scope.$on('$destroy', function() { iElement.off("focus") })
}
};
}]);
And this is view:
<input type="text" datepicker-popup="" ng-model="ctrl.dt" auto-open />
This is the older solution:
You can write a directive to change the value of is-open when input focuses:
app.directive("autoOpen", ["$parse", function($parse) {
return {
link: function(scope, iElement, iAttrs) {
var isOpenVarName = iAttrs.isOpen;
iElement.on("focus", function() {
$scope.$apply(function() {
$parse(isOpenVarName).assign(scope, "true");
});
});
}
};
}]);
and here is the view:
<input type="text" datepicker-popup="" auto-open is-open="open" ng-model="ctrl.dt" />
Note that, you have to define open in your controller and place is-open="open" in input element. I know this is not the best solution. I will make it better as soon as find a better solution.
Update : As #Akos-lukacs mentioned in comments, this solution does not work when disabling debug data in angular.

alisabzevari's answer seems fine to me, but you might be better off just doing this:
ng-focus='open = true'
I struggled to wrap my head around how exactly is-open works, but I ended up just making a wrapper directive that does all the typical setup for my datepickers and sets up a separate scope for the is-open state:
app.directive('datepickerAuto', function() {
return {
require: ['ngModel'],
restrict: 'E',
template: '<input class="input form-control" datepicker-popup="MM/dd/yyyy" show-weeks="false"' +
' is-open="autoIsOpen" ng-focus="autoIsOpen = true" ng-click="autoIsOpen = true"'
+' type="text" ng-model="ngModel" ng-model-options="{\'updateOn\': \'blur\'}"/>',
link: function(scope) {
scope.autoIsOpen = false;
},
scope: {
ngModel: '='
}
};
});
All I have to do is this now:
<datepicker-auto ng-model="someDate"></datepicker-auto>

Related

input file change listener in a directive doesnt update scope variable [plunker attached]

I have a directive that contains file input. On change of file input I try to update some scope variables, it doesn't update it. When the commented out timeout is uncommented scope variables are updated.
I was under the impression that angular.element .on function does the safe apply (triggering a digest). I am not sure why it requires another $timeout here to work, Could someone shed some light on this behaviour?
Problem reproduced in below plunker.
https://plnkr.co/edit/dHRInri9i21bR0gxe8q1?p=preview
app.directive('fileInput', function($timeout) {
var directive;
directive = {
restrict: 'E',
templateUrl: 'fileinput.html',
link: function(scope, element) {
element
.find('input')
.on('change', function(e) {
console.log(e);
scope.fileName = 'file name--->' + e.target.files[0].name;
/*$timeout(function(){
scope.fileSize = 'fileSize--->' + e.target.files[0].size;
});*/
});
}
};
return directive;
});
directive template:
<input type="file" id="fileUpload" accept="image/*" />
<br>
{{fileName}}
<hr>
{{fileSize}}
element.on is either using jqLite or Jquery. So using scope.$apply is valid in this case as element.on is not AngularJs aware
plunker: https://plnkr.co/edit/hohU97QmjASwat139sEV?p=preview

AngularJS prevent ngModel sync

I have a simple directive called po-datepicker, it displays a datepicker on the screen, but allows the user to type a date manually:
<input type="text" ng-model="model" po-datepicker required />
and this is the directive:
myApp.directive('poDatepicker', function () {
return {
require: ['?^ngModel'],
restrict: 'A',
link: function ($scope, elem, attrs, ctrl) {
var ngModel = ctrl[0];
var picker = elem.datepicker();
picker.on('changeDate', function(e) {
ngModel.$setViewValue(e.date);
...
});
elem.parent().find('button').on('click', function() {
picker.datepicker('show');
});
var changeFn = function(e) {
// Here I have some logic that calls $setViewValue();
};
picker.on('hide', changeFn);
elem.on('keyup blur', changeFn);
}
};
});
this works as expected, but when I try to type a value in the input, it updates the ngModel, changing the variable in the scope, how can I prevent ngModel from being changed in the input?
Here is a plunkr, try manually writing a value and you'll understand what I'm talking.
Actually, after some research, I found a solution for this problem.
What I found on forums and questions is that I needed to unbind the element's events, like this:
elem.unbind('input').unbind('keydown').unbind('change');
But that solution didn't work as expected.
The problem is that I'm currently using Angular 1.2.x, I found out that you need also to set some priority to the directive, such as:
return {
require: ['?^ngModel'],
priority: 1,
...
}
The priority: 1 is needed in this case, because of the priority of some internal Angular.js directives.
Here is an updated plunker with the right priority set up.
Just add 'disabled' to the input http://plnkr.co/edit/xFeAmSCtKdNSQR1zbAsd?p=preview
<input type="text" class="form-control" ng-model="test" po-datepicker required feedback disabled/>

When using two way binding in angular, when are the binded variables actually available?

I'm writing a directive that uses two-way binding.My directive looks like this:
bankSearch.directive('bankSearch',
function() {
return {
restrict: 'E',
scope: {
bankDetail: '='
},
templateUrl: "angular/views/self_signup/bank_search.html",
link: function(scope) {
//Now when link function runs, scope.bankDetail is undefined.
}
}
});
Html of template-url:
`<div class="row-fluid">
<input id="ifsc-code" class="span12" type="text" name="ifscCode"
ng-model="bankDetail.bankBranch.ifscCode"
should-be-ifsc
ng-keypress="onPressEnter($event, bankSearch.ifscCode.$valid)">
</div>`
This is how I'm using the directive:
`<bank-search
bank-detail="bankSearchModel.bankDetail">
</bank-search>`
I was under the impression that link function runs after linking(watchers setup) is done. If I'm correct then why am I getting undefined for scope.bankDetail inside my link function.
I'm new to Angular. Thanks for the help!
Might be bankSearchModel.bankDetail defines after directive is rendered. In case it is loaded from $http or something else. Try
link: function(scope) {
scope.$watch('bankDetail', function(val){
console.log(val);
});
}
And you'll see all changes of that variable.

Angular.js child input element not getting parents scope

This should be pretty simple, but for some reason when I have
<div class="file-navigator" ng-controller="FileSystemCtrl">
<input type="file" id="openFile" ng-model="path" ng-change="openFolder()" nwdirectory />
The ng-change doesn't get triggered.
If I use
onchange="angular.element(this).parent().scope().openFolder()"
the onchange event gets triggered, but obviously, that's ugly.
The FileSystemCtrl is defined as a module which I'm importing into my app, it's structured like this.
angular.module('myApp.FileSystemModule',[])
.factory('FileSystemModel',function($rootscope){...})
.controller('FileSystemCtrl',function(){...});
Any ideas why the child doesn't know about it's parent controller? Particularly as the child doesn't have a controller of it's own?
AngularJs doesn't support input with type file. See this issue. And this. Your onchange event is the best option for now.
Another way would be to use a directive taking advantage of $compile to interact with a ng-model:
.directive('path', function($compile) {
return {
restrict: 'E',//<path></path> in your markup
replace: true,
template: '<input type="file" />',
link: function(scope, elem, attrs) {
var textField = $(elem).attr('ng-model', 'something');
$compile(textField)(scope);
$(elem).change(function() {
//do stuff
});
}
};
});
I didn't test it, but it provides you with a get-go.

angularjs - need help for delayed search directive

fiddle here: http://jsfiddle.net/graphicsxp/QA4Fa/2/
I'm triying to create a directive for searching. Basically it's just a textbox that detects user input and after a 1 second delay, a search method is called.
It's not working yet and I'm having two issues.
First, why is the filterCriteria not updated in the span when user inputs text ?
Second, the watch on filterCriteria is triggered at page loading but not when text is entered in the textbox.
<div ng-app="myApp" ng-controller="myController">
<delayed-search ng-model="filterCriteria"></delayed-search>
<span>filter criteria is : {{filterCriteria}}</span>
</div>
angular.module('myApp', []).directive("delayedSearch", ['$timeout', function($timeout) {
return {
restrict: "E",
template: '<input type="text" />',
scope: {
filterCriteria : '='
},
link: function (scope, element, attrs) {
},
controller: function ($scope) {
var timer = false;
$scope.$watch('filterCriteria', function () {
if (timer) {
$timeout.cancel(timer);
}
timer = $timeout(function () {
alert('timeout expired');
}, 1000)
});
}
}
}]).controller('myController', function($scope){ });
You should NOT use a controller with a directive ( until you understand it ! ) .
A controller in a directive is meant for directive to directive communication (I wish they had named it something else!).
#Langdon got it right.. But here is another implementation of the same. Note that in both the answer's the controller is missing.
http://jsfiddle.net/QA4Fa/4/
First, why is the filterCriteria not updated in the span when user inputs text ?
Your scope is wrong, it should be scope: { ngModel : '=' },, and your template should be template: '<input type="text" ng-model="ngModel" />.
Second, the watch on filterCriteria is triggered at page loading but not when text is entered in the textbox.
Same as the first problem, you should be watching ngModel.
Also, you don't need the overhead of a controller for this, you can get away with just using the link function. Here's an updated fiddle: http://jsfiddle.net/QA4Fa/3/

Resources