1

In a nutshell:

I try to do something like this inside my directive - namely change the value of model that is liked to 'trigger' attribute:

angular.element(element).on('hidden.bs.modal', function () {
   scope.$apply(function () {
     attrs.$set('trigger', null);
    });
});

and it does not work. Why? Should I do it other way around?

And here is full story:

I have a dialog that is triggered when showRemoveDialog flag is set. This flag is set when user clicks Remove button.

Here is a dialog's opening tag:

<div remove-dialog trigger="{{showRemoveDialog}}" class="modal fade" id="myModal">

Then I have a directive removeDialog:

myApp.directive("removeDialog", function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs, controller) {
            angular.element(element).on('hidden.bs.modal', function () {
                scope.$apply(function () {
                    attrs.$set('trigger', null);
                });
            });
            attrs.$observe('trigger', function (newValue) {
                if (newValue) {
                    angular.element(element).modal('show');
                } else {
                    angular.element(element).modal('hide');
                }
            });
        },
        controller: 'DeleteController'
    };

});

As you can see, I observe trigger attribute and when it changes to true (user clicks Remove button), I show the dialog:

$scope.remove = function () {
    $scope.showRemoveDialog = true;
};

And it works.

But if the value of trigger changes to false/null I want to close it - for instance Cancel button was clicked, or X icon was clicked. And if one of these two actions occur, I need to set back trigger value to false/null, so that the next time when user click on Remove button value would change from false -> true, and my dialog appears once again.

The problem is that this piece of code does not work:

            angular.element(element).on('hidden.bs.modal', function () {
                scope.$apply(function () {
                    attrs.$set('trigger', null);
                });
            });

I mean it does not set the value of {{showRemoveDialog}} in scope to null. I already tried $apply function, but still in wain.

I guess I'm doing something really wrong in angular. Please help.

2 Answers 2

2

Yes, the idea you have come up with is kind of confusing, changing the attribute will not actually change the scope variable, so to fix this you would have to change the scope variable, in this case you know what the variables name is so it would work, but for other elements you might not know what the variable is. To fix this specific issue you would have to do.

scope.showRemoveDialog = null;
scope.$apply();

This is not very dynamic though. Here is what I would do (not tested).

Pass the variable name in as a string

trigger="showRemoveDialog"   

Then in your directive get some help from $parse

myApp.directive("removeDialog", function ( $parse ) { ....    

The link function...

 link: function (scope, element, attrs, controller) {
   var variableName = attrs.trigger;

        angular.element(element).on('hidden.bs.modal', function () {
            $parse(variableName + ' = null')(scope);
            scope.$apply(); // Might not be needed.
        });
        scope.$watch(variableName, function (newValue) {
            if (newValue) {
                angular.element(element).modal('show');
            } else {
                angular.element(element).modal('hide');
            }
        }, true);  // true might not be needed. 
    },

Also you don't need to do angular.element(element) as the element passed to the link function should already be wrapped.

Sign up to request clarification or add additional context in comments.

4 Comments

This works of course, but I tried to avoid using scope's variables, at least directly. I wanted this directive to be reusable, and not bound to showRemoveDialog variable on the scope.
Updated - What I would do.
Works like a charm. Thanks (scope.$apply(); is needed)
Indeed, I'm having fun: another question: stackoverflow.com/questions/18920155/… if you don't mind checking it :)
0

The first argument to the jQuery on() method is the event you're listening for. I've never seen it used with custom events before, only standard Javascript ones like "keydown". So my first question would be have you tested that the event hook is ever called? If not put a console.log("event called"); before you try to set your element's trigger attribute.

Another thing I would mention is that setting an attribute to null like that wont work. Have a look at the AngularJS source code . Instead I would set the attribute to false.

Lastly I would recommend just using the Angular UI Bootstrap library that includes a nice modal feature - or something else, I don't mind but reinventing the wheel here seems unnecessary.

4 Comments

Angular UI Bootstrap library not yet supports Bootstrap 3, that is why I'm reinventing it :) 'hidden.bs.modal' is custom event of Bootstrap, and of course it works.
Changing null to false didn't help. Thanks though
It does support Bootstrap 3 if you pull this branch and build it yourself. (Work in progress but I did that and it works OK for me, I'm using Bootstrap 3 modals in my project.
I'm using master. Thanks though

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.