Jonathan Robbins
Jonathan Robbins

Reputation: 2047

AngularJS accessing an attribute in a directive from a controller

I need to pass an Id defined in the directive to the associated controller such that it can be used in a HTTP Get to retrieve some data.

The code works correctly in its current state however when trying to bind the Id dynamically, as shown in other questions, the 'undefined' error occurs.

The Id needs to be defined with the directive in HTML to meet a requirement. Code follows;

Container.html

<div ng-controller="IntroSlideController as intro">
   <div intro-slide slide-id="{54BCE6D9-8710-45DD-A6E4-620563364C17}"></div>
</div>

eLearning.js

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

app.controller('IntroSlideController', ['$http', function ($http, $scope, $attrs) {
    var eLearning = this;
    this.Slide = [];
    var introSlideId = '{54BCE6D9-8710-45DD-A6E4-620563364C17}'; //Id to replace

    $http.get('/api/IntroSlide/getslide/', { params: { id: introSlideId } }).success(function (data) {
        eLearning.Slide = data;
    });
}])
    .directive('introSlide', function () {
        return {
            restrict: 'EA',
            templateUrl: '/Modules/IntroSlide.html',
            controller: 'IntroSlideController',
            link: function (scope, el, attrs, ctrl) {
                 console.log(attrs.slideId); //Id from html present here
            }
        };
    });

Upvotes: 0

Views: 88

Answers (2)

b0nyb0y
b0nyb0y

Reputation: 1446

Instead of defining a controller div that wraps around a directive, a more appropriate approach is to define a controller within the directive itself. Also, by defining an isolated scope for your directive, that slide-id will be available for use automatically within directive's controller (since Angular will inject $scope values for you):

.directive('introSlide', function () {
    // here we define directive as 'A' (attribute only)
    // and 'slideId' in a scope which links to 'slide-id' in HTML
    return {
        restrict: 'A',
        scope: {
            slideId: '@'
        },
        templateUrl: '/Modules/IntroSlide.html',
        controller: function ($http, $scope, $attrs) {
            var eLearning = this;
            this.Slide = [];

            // now $scope.slideId is available for use
            $http.get('/api/IntroSlide/getslide/', { params: { id: $scope.slideId } }).success(function (data) {
                eLearning.Slide = data;
            });
        }
    };
});

Now your HTML is free from wrapping div:

<div intro-slide slide-id="{54BCE6D9-8710-45DD-A6E4-620563364C17}"></div>

In your IntroSlide.html, you probably have references that look like intro.* (since your original code use intro as a reference to controller's $scope). You will probably need to remove the intro. prefix to get this working.

Upvotes: 2

Rodrigo Fonseca
Rodrigo Fonseca

Reputation: 944

Require your controller inside your directive, like this:

app.directive( 'directiveOne', function () {
      return {
        controller: 'MyCtrl',
        link: function(scope, el, attr, ctrl){
           ctrl.myMethodToUpdateSomething();//use this to send/get some msg from your controller
        }
      };
    });

Upvotes: 0

Related Questions