0

I create a new Scope within a directive like this

controllersModule.directive('uploadBox', function() {
return {
    restrict: 'E',
    scope: {
        topic: '=topic',
        label: '=label'
    },
    templateUrl: '/assets/directives/uploadBox.html'
};});

And use this directive like this (both values -label and topic- are values, which are stored in JSON files, within two different controllers)

<upload-box label="lc.getTerm('system_upload')" topic="tc.currentTopic.uID"></upload-box> 

So the attribute label and topic are both passed to the new (created) Scope. Now, the funny thing is, while I'm able to access both values within the template HTML file (uploadBox.html)

<div ng-controller="DropUploadCtrl">
    <button class="btn btn-success" dropzone="dropzoneConfig">
        <!-- label is correctly shown -->
        {{ label }}
    </button>

    <!-- this link works fine: Evaluates to something like aaa/54dg54...SHA128-Hash...G4FX-->
    <a ng-href="aaa/{{ topic }}">BB</a>
</div>

Only the label value is accessible from within the DropUploadController.

controllersModule.controller('DropUploadCtrl', ['$scope',function($scope) {
var that = this;

console.log($scope.label); // this is working fine
console.log($scope.topic); // this is undefined

// some more stuff here

}]);

I know that scopes are created for specific controllers and you cannot share scope variables directly between two controllers. However, I don't think that this is a problem here because I can use the label value. But, where am I wrong respectively what is wrong in my code?

Thank you very much

EDIT:

The output for the rootScope within the controller

console.log("$scope::>"); 
console.log($scope.label); 
console.log($scope.topic); 
console.log("$rootScope::>") 
console.log($rootScope.label); 
console.log($rootScope.topic); 

looks like this:

"$scope::>" 
"I'm a label" 
undefined 
"$rootScope::>" 
undefined 
undefined 

Furthermore, the value is undefined in the link function of the directive

Edit2: The solution has been found! The value in tc.currentTopic.uID was not filled at the moment the other controller was initializing. That's why the expression {{topic}} was working fine because it has been evaluated again, when the value has changed, a couple of ms later. I fetch the data now directly via $routeParams.

PlasmaLampe
  • 129
  • 2
  • 12

2 Answers2

1

Directives have isolated scopes. Since you added:

 scope: {
        topic: '=topic',
        label: '=label'
    },

it created an isolated scope. But, angular documentation says: = or =attr - set up bi-directional binding between a local scope property and the parent scope property of name defined via the value of the attr attribute. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given <widget my-attr="parentModel"> and widget definition of scope: { localModel:'=myAttr' }, then widget scope property localModel will reflect the value of parentModel on the parent scope. Any changes to parentModel will be reflected in localModel and any changes in localModel will reflect in parentModel.

Link here

Cristi Berceanu
  • 1,693
  • 1
  • 10
  • 12
  • The output for the rootScope within the controller console.log("$scope::>"); console.log($scope.label); console.log($scope.topic); console.log("$rootScope::>") console.log($rootScope.label); console.log($rootScope.topic); looks like this: "$scope::>" "I'm a label" undefined "$rootScope::>" undefined undefined It's interesting that I can access the topic in the HTML template BB – PlasmaLampe Jan 05 '15 at 20:46
  • Are you pulling $scope.label and $scope.topic from the server in a $http or $resource call in your controller at any point? It would be helpful to see all appearances of $scope.label and $scope.topic in your controller. – Cristi Berceanu Jan 05 '15 at 20:52
  • nope, everything is handled on client side. I think the main question is: what is the difference between the access in the controller from the access via ng-href="aaa/{{ topic }}" within the template, isn't it? – PlasmaLampe Jan 05 '15 at 20:54
  • can you please paste your whole snippet(or at least appearances of `$scope.label` and `$scope.topic`). Also, can you try passing a constant like `10` to `topic`(instead of `tc.currentTopic.uID`) and see what happens – Cristi Berceanu Jan 05 '15 at 20:56
  • you can access the directive here http://pastebin.com/WgfsZYP6 and the controller here pastebin.com/ZCRJNLX5 Also, here is the HTML template which works fine http://pastebin.com/xFyT54sT – PlasmaLampe Jan 05 '15 at 21:14
  • well the constant '10' is defined! Now, why does this happen? ;-) – PlasmaLampe Jan 05 '15 at 21:18
  • From angular documentation: = or =attr - set up bi-directional binding between a local scope property and the parent scope property of name defined via the value of the attr attribute. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given and widget definition of scope: { localModel:'=myAttr' }, then widget scope property localModel will reflect the value of parentModel on the parent scope. Any changes to parentModel will be reflected in localModel and any changes in localModel will reflect in parentModel. – Cristi Berceanu Jan 05 '15 at 21:33
  • thank you! I have found the problem. The value in tc.currentTopic.uID was not filled at the moment the other controller was initializing. That's why the expression {{topic}} was working fine because it has been evaluated again, when the value has changed, a couple of ms later. I fetch the data now directly via $routeParams. – PlasmaLampe Jan 06 '15 at 16:01
0

First thing, if you run console.log(scope.label); in your directive's link function (which you don't have at the moment, you'd have to add it), is it getting a value?

Secondly, it looks like you want the directive to change a value in the parent controller's scope. Sometimes you can get strange things happening when you do this. In this answer, it recommends wrapping those values in your controller in an object.

Community
  • 1
  • 1
Joao
  • 2,696
  • 2
  • 25
  • 35
  • the value is also undefined in the link function. – PlasmaLampe Jan 05 '15 at 20:52
  • Then the directive isn't getting a value for topic at all. But since it seems to be getting it at some point (which is why it will output in it's template) it leads me to believe `topic` is waiting on a promise of some kind which resolves after `console.log()` is called. If so, I suggest you try wrapping that code in the controller in a promise callback (ex: `then()`). – Joao Jan 06 '15 at 17:16