0

We are using bootstrap datepicker for our project needs. What we need to do is that whenever user selects the today's date, date has to be shown appended with "(TODAY)" like "May 12, 2008 (TODAY)" in the textbox.

What can be the best approach here? As we are using this datepicker at multiple places, I think having a general approach like creating a directive would be helpful. Was trying to bind change event with the datepickerPopup directive, but have not been able to make it work.

Here is what I have tried so far:

Have created one decorator. This seems to be working. However one issue, how do I access the parent directive methods in this decorator (such as dateFilter, parseDate here)? (sorry if you find my questions naïve, as I am very new to angularjs). I have attached the code.

app.config(function($provide) {
$provide.decorator('datepickerPopupDirective', function($delegate) {
    var directive = $delegate[0],
        link = directive.link;
     //closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection,
    //angular.extend(directive.scope, { 'monthChanged': '&' });

    directive.compile = function() {
        return function(scope, element, attrs, ngModel) {
            link.apply(this, arguments);

                ngModel.$render = function() {
                    var date = ngModel.$viewValue ? dateFilter.apply(ngModel.$viewValue, dateFormat) : '';
                    var currentDate = new Date();
                    currentDate.setHours(0,0,0,0);

                    if(date.getTime() == currentDate.getTime()){
                        element.val(date + "(TODAY)");
                    }else{
                        ngModel.$setViewValue(scope.date);
                    }                               
                    scope.date = parseDate( ngModel.$modelValue );
                  };
        };
    };
    return $delegate;
});

});

1 Answers1

0

You've got a couple of options. The quick and dirty way would be to extract the component from the third party library into your own directive and template, and modify as needed. The disadvantage to this is that you'll no longer be up to date with the component. Future versions would require you to manually update your directive, which you might not care about... yet.

The second option, is to take advantage of angular's $provide.decorator

This post gives you an initial idea

What are "decorators" and how are they used?

Here's a basic example of decorating a directive definition object

app.directive("foo", function() {
  return {
    replace: true,
    template: '<div>This is foo directive</div>'
  };
});

app.config(function($provide) {
  $provide.decorator('fooDirective', function($delegate) {
    var directive = $delegate[0];

    directive.restrict = "AM";
    return $delegate;
  });
});

In your case, you'll want to override what value is being referenced on the template. You could decorate the entire directive if you want to completely modify it.

I would recommend this as the best approach when looking to tackle modification of a third party library.

Here's an example of decorating a directive to override a scope level function, and use an existing scope variable within the directive while overriding it.

https://jsfiddle.net/wvty8rpc/3/

Community
  • 1
  • 1
domitall
  • 655
  • 5
  • 15
  • Thanks @domitall for the help. Have created one decorator. This seems to be working. However one issue, how do I access the parent directive methods in this decorator? (sorry if you find my questions naïve, as I am very new to angularjs). I have attached the code in my next response. – Narinder Goyal May 12 '15 at 18:32
  • I've updated my answer to include a fiddle that gives an example of accessing a method from the original directive and overriding it. No question is a bad question! – domitall May 12 '15 at 19:26