0

Problem: The attribute I pass to my directive's controller is not evaluated. For example, I get {{ attribute.value }} instead of 5.

Desired Outcome: My directive's controller has access to a primary key contained in an object from a parent controller. I need it to make API calls like MyResource.save({id: attribute});.

Code Snippets:

Calling directive from HTML

<div ng-controller="BoatDetailController as boatCtrl">
  <div class="row">
    <booking-widget boat-id="{{ boatCtrl.boat.id }}"></booking-widget>
  </div>

Directive

(function () {
    'use strict';

    angular.
        module('trips').
        directive('bookingWidget', bookingWidget);

    bookingWidget.$inject = [];

    function bookingWidget() {
        return {
            restrict: 'E',
            scope: {
                boatId: '@'
            },
            templateUrl: "/static/app/trips/trips.bookingwidget.template.html",
            controller: 'BookingWidgetController as bookingCtrl'
        }
    }
})();

Controller

(function () {
    'use strict';

    angular.
        module('trips').
        controller('BookingWidgetController', BookingWidgetController);

    BookingWidgetController.$inject = ['Trip', 'Booking', 'Messages', '$scope', '$attrs'];

    function BookingWidgetController(Trip, Booking, Messages, $scope, $attrs) {
        var vm = this;

        vm.boatId = $attrs.boatId;
        ...

        activate();

        //////////////////////////////

        function activate() {
            console.log(vm.boatId);
            //
        }

Console Results:

With $scope.boatId: (logs a blank line)

With $attrs.boatId: {{ boatCtrl.boat.id }} (a string)

Recap: The boat-id attribute of my directive is not resolving. Can you help me figure out how to fix it?

4
  • hey, did you try accessing the attributes and their values in the link function of the directive? Commented Oct 26, 2015 at 6:31
  • I haven't! To be honest, I'm not sure how... I'm very confused about this, though. There is (on the same project) a working directive with this same structure. The only difference is that (in this case) I need to use the attribute in the controller instead of the template. How would you go about accessing the attribute in a link function then accessing it from the controller? Commented Oct 26, 2015 at 6:35
  • I have successfully logged the value to the console using attrs.$observe in a link function. Any ideas on how to get this to the controller? Could I use bookingCtrl.boatId = value;? Commented Oct 26, 2015 at 6:45
  • you have the scope available in link function. You can store in on the scope object in link function, and access the same in controller. Commented Oct 26, 2015 at 6:47

2 Answers 2

1

You can actually create a custom directive like this:

function bookingWidget() {
        return {
            restrict: 'E',
            scope: {
                boatId: '@'
            },
            templateUrl: "/static/app/trips/trips.bookingwidget.template.html",
            controller: 'BookingWidgetController as bookingCtrl',
            link : function(scope, element, attrs, controller){
               console.log(attrs.boatId);
               scope.boatId = attrs.boatId;
            }
        }
    }

The link function actually allows you to have an access to the element, the scope of the directive, the attributes associated to the directive and the controller of the directive. The function is called after everything associated to the directive has been performed. In other words, this is the last stage.

The same scope would be shareable between the link function and controller.

Now, to make the API call, you may actually add a function in your controller that accepts the boatID, makes a call to the API and accepts the response onto the controller object. After that, add a watcher within the link function that watches over "vm.boatId", within which you may call that function which makes the API call. So, even if the controller has initialized before the link function, you would still be able to perform what you wish to. So, it would be a "link-based activation".

You may give this solution a try. Hope it helps.

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

7 Comments

I'm so close to understanding, but not quite there. In the controller, how would I call the value? $scope.boatId still logs a blank line.
@PANDAStack: within the link function, are you able to get the value of scope.boatId? If so, then, you must be having scope.bookingCtrl available within the link function. You can assign scope.bookingCtrl.boatId = attrs.boatId.
Yes. Within link I can log 45 for example, the correct boat primary key. I will continue to try to find a way to access within the controller.
@PANDAStack: can you check whether you have the scope.bookingCtrl available within the link function?
I do have it. And in fact, it shows that I have correctly passed boatId into the controller. I think the issue might be that link runs last. The controller function runs first. So by the time link has had a chance to assign a value, code within controller will already be running.
|
0

You can pass a function and call it. Need to use & then.

https://thinkster.io/egghead/isolate-scope-am

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.