Multiple custom directives on 1 page with callbacks

I created a custom directive (with some help from SO). This is a full screen date picker that uses ngModel to set the date when the user picks a date. At the same time, it calls a callback function that is set when the directive is added to the page. The problem is that if I put 2 date pickers on the assembly, it always tries to call the callback from the second.

Here is the HTML ...

<fp-date-picker ng-model="dateOne" on-select="dateSelectedOne()"></fp-date-picker>

<fp-date-picker ng-model="dateTwo" on-select="dateSelectedTwo()"></fp-date-picker>

      

Here is my directive with most of it removed for brevity

angular.module('directives').directive('fpDatePicker', ['$parse', function ($parse) {

    return {

        restrict: 'EA',
        require: 'ngModel',
        templateUrl: '/templates/fpDatePicker.tpl.html',

        link: function($scope, $element, $attrs, ngModel){

            // A callback executed when a date is selected
            var onSelectCallback = $parse($attrs.onSelect);


            // Set current month
            $scope.selectedDate = moment();



            // Set date when one is clicked
            $scope.selectDate = function(day){

                var selectedDay = day.number;
                var selectedMonth = $scope.currentMonth.format('MM');
                var selectedYear = $scope.currentMonth.format('YYYY');

                $scope.selectedDate = moment(selectedYear + '-' + selectedMonth + '-' + selectedDay, 'YYYY-MM-DD');

                // Update the model
                ngModel.$setViewValue($scope.selectedDate);


                // Call the on-select callback
                onSelectCallback($scope);

            };


        }


    };

}]);

      

And just in case when needed, here is my directive template ...

<div class="fpDatePicker-controls">
    <a href="#" ng-click="previousMonth()">&lt;</a>
    <a href="#" ng-click="nextMonth()">&gt;</a>
</div>
<div class="fpDatePicker-month">
    <a class="fpDatePicker-day" 
        ng-repeat="day in currentMonth.days" 
        ng-click="selectDate(day)"
    >
        {{day.number}}
    </a>
</div>

      

I thought the problem with it always using a callback from the last instance of a directive on the page could be because the variables in the link function are global to all instances of that directive or $ attrs are not attrs of the current directive instance, but I used console .log () to show $ attrs and it was different in each case.

I also wondered if this was due to the scoping being allocated, but although the callback functions are in scope, the expression in the attributes is not part of the scope, it is the attribute being passed.

Very confused, any help would be really appreciated.

UPDATE: Plunkr created

http://plnkr.co/edit/nU27Wjpu3UYCR9q6DnLw?p=preview

+3


source to share


1 answer


Your problem is because your directive is independent of the isolated scope. Thus, both instances of the directive have the same scope. When the second directive is created, it overrides all scope variables.

You can read more about sandboxed scope in the doc: https://docs.angularjs.org/guide/directive .

Here is a daemon showing how to use isolated scopes: http://plnkr.co/edit/U64sbukqfFW0NQmvIC1a

I've updated your markup to make it compatible with the controller like the syntax:



<body ng-controller="MainCtrl as main">
    {{main.dateOne}}
    <fp-date-picker ng-model="main.dateOne" on-select="main.dateSelectedOne()"></fp-date-picker>

    <br />
    <br />
    <br />

    {{main.dateTwo}}
    <fp-date-picker ng-model="main.dateTwo" on-select="main.dateSelectedTwo()"></fp-date-picker>

</body>

      

The main change to your directive definition is the use of the scope attribute on the scoped directive definition object:

.directive('fpDatePicker', function() {

    return {
      scope: {
        select: '&onSelect'
      },

      restrict: 'EA',
      require: 'ngModel',
      templateUrl: 'datepicker.html',

      link: function($scope, $element, $attrs, ngModel) { ... }
     };
  })

      

Please note that your code still has date picking issues. By clicking on the day, select the date of the previous day. I didn't fix it. Let me shut up if you need help.

+3


source







All Articles