Call method in directive controller from other controller

angularjs, angularjs-directive, javascript, jquery

Solution

This is an interesting question, and I started thinking about how I would implement something like this.

I came up with this (fiddle);

Basically, instead of trying to call a directive from a controller, I created a module to house all the popdown logic:

var PopdownModule = angular.module('Popdown', []);

I put two things in the module, a `factory` for the API which can be injected anywhere, and the `directive` for defining the behavior of the actual popdown element:

The factory just defines a couple of functions `success` and `error` and keeps track of a couple of variables:

PopdownModule.factory('PopdownAPI', function() {
    return {
        status: null,
        message: null,
        success: function(msg) {
            this.status = 'success';
            this.message = msg;
        },
        error: function(msg) {
            this.status = 'error';
            this.message = msg;
        },
        clear: function() {
            this.status = null;
            this.message = null;
        }
    }
});

The directive gets the API injected into its controller, and watches the api for changes (I'm using bootstrap css for convenience):

PopdownModule.directive('popdown', function() {
    return {
        restrict: 'E',
        scope: {},
        replace: true,
        controller: function($scope, PopdownAPI) {
            $scope.show = false;
            $scope.api = PopdownAPI;

            $scope.$watch('api.status', toggledisplay)
            $scope.$watch('api.message', toggledisplay)

            $scope.hide = function() {
                $scope.show = false;
                $scope.api.clear();
            };

            function toggledisplay() {
                $scope.show = !!($scope.api.status && $scope.api.message);               
            }
        },
        template: '<div class="alert alert-{{api.status}}" ng-show="show">' +
                  '  <button type="button" class="close" ng-click="hide()">&times;</button>' +
                  '  {{api.message}}' +
                  '</div>'
    }
})

Then I define an `app` module that depends on `Popdown`:

var app = angular.module('app', ['Popdown']);

app.controller('main', function($scope, PopdownAPI) {
    $scope.success = function(msg) { PopdownAPI.success(msg); }
    $scope.error   = function(msg) { PopdownAPI.error(msg); }
});

And the HTML looks like:

<html ng-app="app">
    <body ng-controller="main">
        <popdown></popdown>
        <a class="btn" ng-click="success('I am a success!')">Succeed</a>
        <a class="btn" ng-click="error('Alas, I am a failure!')">Fail</a>
    </body>
</html>

I'm not sure if it's completely ideal, but it seemed like a reasonable way to set up communication with a global-ish popdown directive.

Again, for reference, the fiddle.

Problem

I have a directive that has its own controller. See the below code: ``` var popdown = angular.module('xModules',[]); popdown.directive('popdown', function () { var PopdownController = function ($scope) { this.scope = $scope; } PopdownController.prototype = { show:function (message, type) { this.scope.message = message; this.scope.type = type; }, hide:function () { this.scope.message = ''; this.scope.type = ''; } } var linkFn = function (scope, lElement, attrs, controller) { }; return { controller: PopdownController, link: linkFn, replace: true, templateUrl: './partials/modules/popdown.html' } }); ``` This is meant to be a notification system for errors/notifications/warnings. What I want to do is from another controller (not a directive one) to call the function `show` on this controller. And when I do that, I would also want my link function to detect that some properties changed and perform some animations. Here is some code to exemplify what I'm asking for: ``` var app = angular.module('app', ['RestService']); app.controller('IndexController', function($scope, RestService) { var result = RestService.query(); if(result.error) { popdown.notify(error.message, 'error'); } }); ``` So when calling `show` on the `popdown` directive controller, the link function should also be triggered and perform an animation. How could I achieve that?

Original source

Related problems