2

I'm using angular strap datepicker and I want to execute some of my own logic when the datepicker opens up and closes.

How can I recognize these events inside my controller, and bind to them?

and not just to the datepicker events, but any of angular straps events for that matter.

An example of what I want to do:

http://plnkr.co/edit/Uy1Lz6I0NWSACV4kyljk?p=catalogue

Julia Vi
  • 113
  • 1
  • 9

2 Answers2

3

Let's say you want to get the selected date in your controller and do something with it:

Add this to your controller:

$rootScope.$watch('datepickerDateSelected', function(date){
    // do whatever you want with the date parameter here
});

And modify the datepicker directive $scope.select method, like this:

scope.$select = function (date) {
    $rootScope.datepickerDateSelected = date; // ADD THIS
    $datepicker.select(date);
};

[ UPDATE ]

Using $broadcast/$on. Modify the directive ($datepicker.show and $datepicker.hide methods) like this:

$datepicker.show = function(){
    ...
    $rootScope.$broadcast('opening'); // ADD THIS
    ...
}

 $datepicker.hide= function(blur){
    ...
    $rootScope.$broadcast('closing'); // ADD THIS
    ...
}

And in your controller, add this (you don't need to $watch anything):

$rootScope.$on('opening', function(event, data) { console.log("it's opening!"); });
$rootScope.$on('closing', function(event, data) { console.log("it's closing!"); });

It worked in my case, but you may want to check this: Working with $scope.$emit and $scope.$on (see answer from zbynour)

If you don't want to use $broadcast/$on (see the comments), just use $watch like in the first example instead.

Community
  • 1
  • 1
Edd
  • 932
  • 10
  • 24
  • Yeah, it's a workaround. Now that I think about it, you could also `$emit` a `datePickerDateSelected` event passing also the `date` as a value, and listen for that event with `$on` wherever you want to use the selected date. In this way you would avoid creating an attribute on the ``$rootScope`. Anyway, the difference is very minimal. – link Jul 08 '14 at 08:04
  • Apart from the fact that the OP wants to react to the `open` and `close` events, not on the `dateSelected` event... – link Jul 08 '14 at 08:04
  • Ooops. You are absolutely right, @link. However I just wanted to give an example on how to watch a variable and change it within the directive. Anyway, the directive does have $datepicker.show and $datepicker.hide methods - although they BOTH execute whenever the user opens/closes the calendar, I'm sure it's possible to do something with it. PS: I like the $emit event possibility, too, although it does seem to have some caveats: http://stackoverflow.com/questions/21402756/angularjs-emit-only-works-within-its-current-scope – Edd Jul 08 '14 at 14:40
  • Maybe $rootScope.$broadcast(someEvent) and $on(someEvent) would also do the trick: http://stackoverflow.com/questions/14502006/scope-emit-and-on-angularjs – Edd Jul 08 '14 at 14:48
  • If you use `$rootScope` as an event bus (that is, you `$emit` from `$rootScope` and you listen through `$on` from `$rootScope`) then `$emit` it's better than `$broadcast`. Broadcasting will bubble the event down the scopes, resulting in a performance loss. Emitting the event from rootScope guarantees that only rootScope itself can react to it, and it's more efficient in cases like this – link Jul 08 '14 at 14:58
  • I just updated my answer to fit the OP needs. NOTE: it did work by using $scope instead of $rootScope in my controller. I don't know about performance, didn't test it but I'm guessing it's not a problem for a small scale app. Anyway, OP can use $emit instead I guess :) – Edd Jul 08 '14 at 15:01
  • If you use the current `scope` you have to be careful about emitting or broadcasting, because the hierarchy of the scopes matters. The `emit` performance consideration is valid only for `$rootScope`. – link Jul 08 '14 at 15:15
0

I checked the code for AngularStrap's datepicker. They provide a $datepicker service which I thought could be decorated to achieve what you wanted, but this should be done in the config phase of your app, and the service would require a DOM element to be initialized. Thus, I think this solution is not feasible.

Anyway, I looked at Angular-UI's datepicker, and it provides attributed to specify functions to use for the open and close events. It would be much easier to use those and emit your events there.

link
  • 1,676
  • 1
  • 13
  • 21
  • Thank you but I wasn't able to find the "attributed to specify functions to use for the open and close events" Could you please give me an example of how to do so? – Julia Vi May 12 '14 at 11:45
  • Look at the [plunkr](http://plnkr.co/edit/?p=preview) they provide as an example, specifically at the Popup datepicker. At line 25, they bind a button to the `open` function declared in the controller's scope. That function changes the value of the `opened` variable, that controls whether the datepicker is open/closed. You could watch that variable to execute your custom logic. – link May 12 '14 at 11:52
  • I just realized you were talking about Angular UI, I have to find a solution for angular strap – Julia Vi May 13 '14 at 09:02
  • I'm afraid that there is no simple soution for AngularStrap, except modifying the code by yourself. Why can't you create a custom build of AngularStrap that excludes the DatePicker module, and use the DatePicker of AngularUI? – link May 13 '14 at 09:08