0

I'm trying to change a scope value in a parent controller from a child directive.

I've added = for two-way binding such that when I click on a the directive's <tr>, it will fire openDetail, which will update scope.page, which has been two-way bound.

Yet it's not updating the controller's page value.

Controller HTML:

TEST : {{page}} //Not changed

<questions-list></questions-list>

Controller:

$scope.page = 'Not changed';

Directive HTML:

<tr ng-repeat="q in questions" ng-click="openDetail( q.id )">

"Questions List" Directive:

scope: {
    page : '='
},
...

scope.openDetail = function (id) {
    scope.page = 'question_detail';
};

In other examples, the ng-click handlers are always bound on the Controller. In my case, I need to fire an event from the directive, change directive value, and have it update the controller.

2
  • at child controller add scope: true; Commented Jun 9, 2016 at 5:48
  • Can you provide a fiddle? Commented Jun 9, 2016 at 6:05

4 Answers 4

3

You should pass the parent scope's property to bind to via directive's element attribute:

<questions-list page="page"></questions-list>

Here the demo.

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

4 Comments

Wait why do u need to call the attribute AND the value both page?
attribute is the name of scope property defined in directive. value is the scope property defined in controller that you need to pass to directive for two way binding.
The attribute name is the property name of the directive's scope, the value is the property of the parent scope to bind to.
@Growler, as to "why" - as a directive's user you choose which properties of your parent scope to pass to it. It's not up to directive to choose. Kind of "modular" approach.
0

I see a mistacke on your html :

<tr ng-repeat="q in questions ng-click="openDetail( q.id )">

must be replace by

<tr ng-repeat="q in questions" ng-click="openDetail( q.id )">

It missing a quote.

And for the problem, you use a primitive type to bind on directve. Try to encapsulate the value into an object on your parent scope :

$scope.page = { value: 'Not changed' };
<questions page="page.value">...</questions>

Comments

0

I can give you some different methods doing this .

Once consider your must pass values from controller to directive

like

scope: {
    page : '='
},

then

You can't access parent scope so need to transclude your child scope hence but it seems deprecated in some versions.

hence best practice is to share page variable with $rootScope.page first inject $rootScope in both controller and directive Injections and use

{{$root.page}}  // in controller 

//and in directive function make this change

scope.openDetail = function (id) {
    $rootScope.page = 'question_detail';
};

Also if you need other ways like #BROADCAST or #EMIT ( really great thing in angularjs)

/// in directive

 $rootScope.$emit("emitName", {page:"page value" }); 

// in controller

 $rootScope.$on("emitName",function(event,data){
       $scope.page = data.page; // this comes from directive and assign to current scope's page variable 
   }); 

Please let me know if anyone works for you otherwise we can research more.

khajaamin

Comments

-1

I created a sample App for you

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

app.controller('testCon', function($scope) {

  $scope.page = "Parent controll";

});

app.directive('questions', function() {

  return {
    scope: true,
    controller: ['$scope',
      function($scope) {

      }
    ]
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test" ng-controller="testCon">
  {{page}}

  <questions>{{page}}</questions>

</div>

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.