Justin Davis
Justin Davis

Reputation: 305

Unable to call Angular directive method

I've got an Angular view thusly:

<div ng-include="'components/navbar/navbar.html'" class="ui centered grid" id="navbar" onload="setDropdown()"></div>
<div class="sixteen wide centered column full-height ui grid" style="margin-top:160px">
    <!-- other stuff -->
    <import-elements></import-elements>
</div>

This is controlled by UI-Router, which is assigning the controller, just FYI.

The controller for this view looks like this:

angular.module('pcfApp')
  .controller('ImportElementsCtrl', function($scope, $http, $location, $stateParams, $timeout, Framework, OfficialFramework) {

    $scope.loadOfficialFrameworks();

    // other stuff here
});

The <import-elements> directive, looks like this:

angular.module('pcfApp').directive('importElements', function($state, $stateParams, $timeout, $window, Framework, OfficialFramework) {

  var link = function(scope, el, attrs) {

    scope.loadOfficialFrameworks = function() {
      OfficialFramework.query(function(data) {
        scope.officialFrameworks = data;
        $(".ui.dropdown").dropdown({
          onChange: function(value, text, $item) {
            loadSections($item.attr("data-id"));
          }
        });
        window.setTimeout(function() {
          $(".ui.dropdown").dropdown('set selected', data[0]._id);
        }, 0);
      });
    }

  return {
    link: link,
    replace: true,
    templateUrl: "app/importElements/components/import_elements_component.html"
  }

});

I was under the impression that I'd be able to call the directive's loadOfficialFrameworks() method from my controller in this way (since I'm not specifying isolate scope), but I'm getting a method undefined error on the controller. What am I missing here?

Upvotes: 0

Views: 591

Answers (2)

TwitchBronBron
TwitchBronBron

Reputation: 3186

The problem is that your controller function runs before your link function runs, so loadOfficialFrameworks is not available yet when you try to call it.

Try this:

angular.module('pcfApp')
  .controller('ImportElementsCtrl', function($scope, $http, $location, $stateParams, $timeout, Framework, OfficialFramework) {
    //this will fail because loadOfficialFrameworks doesn't exist yet.
    //$scope.loadOfficialFrameworks();

    //wait until the directive's link function adds loadOfficialFrameworks to $scope
    var disconnectWatch =  $scope.$watch('loadOfficialFrameworks', function (loadOfficialFrameworks) {
        if (loadOfficialFrameworks !== undefined) {
            disconnectWatch();
            //execute the function now that we know it has finally been added to scope   
            $scope.loadOfficialFrameworks();
        }
    });
});

Here's a fiddle with this example in action: http://jsfiddle.net/81bcofgy/

Upvotes: 2

ilyass
ilyass

Reputation: 402

The directive scope and controller scope are two differents object you should use in CTRL $scope.$broadcast('loadOfficialFrameworks_event');

//And in the directive

scope.$on('loadOfficialFrameworks_event', function(){
scope.loadOfficialFrameworks(); 

})

Upvotes: 0

Related Questions