1

I try to make my own button using directive. The dialog (bootstrap.dialog) should be hired after clicking the button. But, it won't. Tried without click event, it works.

Using this: - AngularJS v1.0.8 - Bootstrap 2.3.2 - Angular-bootstrap 0.3.0

here's my directive...

.directive("ucayButton", function($dialog) {
   return {
        restrict: 'EA',
        template: '<button ng-transclude></button>',
        replace: true,
        transclude: true,
        link: function(scope, element, attrs) {
            element.addClass('btn btn-primary');
            var t = '<div class="modal-dialog">' +
                      '<div class="modal-content">' +
                        '<div class="modal-header">' +
                         '<button type="button" class="close" ng-click="close()" aria-hidden="true">&times;</button>' +
                          '<h4 class="modal-title">Modal title</h4>' +
                        '</div>' +
                        '<div class="modal-body">' +
                          '<p>One fine body&hellip;</p>' +
                        '</div>' +
                        '<div class="modal-footer">' +
                          '<button type="button" class="btn btn-default" ng-click="close()">Close</button>' +
                          '<button type="button" class="btn btn-primary" ng-click="close()">Save changes</button>' +
                        '</div>' +
                      '</div><!-- /.modal-content -->' +
                    '</div><!-- /.modal-dialog -->';

            var modalOpts = {
              backdrop: true,
              keyboard: true,
              backdropClick: true,
              template:  t,
              controller: 'dialogCtrl'
            };

            scope.openDialog = function(){
              console.log('confirmation called');  //always shown when function was called
              var d = $dialog.dialog(modalOpts);
              d.open().then(function(result){
                if(result)
                {
                  alert('dialog closed with result: ' + result);
                }
              });
            };
            angular.forEach(element, function(el) {
              el.addEventListener('click', function() {
                scope.openDialog();  // the function was hired, but the dialog didn't
              });
            });
            scope.openDialog();   //hired
        }
    };
})

1 Answers1

1

addEventListener is not an angular function, so when you perform code that affects $scope variables you need to get those changes back into the digest cycle.

Try this instead:

el.addEventListener('click', function() {
    if(scope.$$phase) {
        scope.openDialog();
    } else {
        scope.$apply(function() {
            scope.openDialog();
        });
    }
});

This checks the $$phase of the scope, which is truthy if you are running code from within a digest cycle. If you are already in a digest cycle then there is no need to wrap the code with an $apply call. If you are not then wrapping the code in an $apply call lets angular know that it needs to digest the changes you are making.

Pete Martin
  • 856
  • 7
  • 15
  • Thanks, Pete. U've saved my day. And, got an enlightenment how to use $$phase and $apply. Huge thanks. ^_^ – user2842277 Oct 03 '13 at 11:26
  • Pleasure. There's a lot more insight into the digest cycle and scope inheritance [here](http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs). Please mark the answer as correct if it solves your issue. :) – Pete Martin Oct 03 '13 at 11:43
  • that's an awesome answer. It should be in the angular's documentation ^_^ – user2842277 Oct 03 '13 at 11:49