user3871
user3871

Reputation: 12718

Update parent controller value from child angular function

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.

Upvotes: 0

Views: 2994

Answers (4)

Alexander Kravets
Alexander Kravets

Reputation: 4395

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.

Upvotes: 3

khajaamin
khajaamin

Reputation: 876

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

Upvotes: 0

Silvinus
Silvinus

Reputation: 1445

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>

Upvotes: 0

Azad
Azad

Reputation: 5264

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>

Upvotes: -1

Related Questions