I'm trying to replace some functionality in an app that I got working with $scope
and $scope.$parent
, where based on behaviour that happens within a child component I can call a method stored in a parent component, on values in the parent.
function ChildController($scope) {
$scope.doThing = function() {
$scope.$parent.doThing()
}
function ParentController($scope) {
...
$scope.stuff = {...};
$scope.doThing = function() {
// does thing to stuff
}
}
These days, I'm using var ctrl = this;
more and I'm wondering how I should handle this. I've experimented with component bindings but it seemed like they were a bit off the mark. Anyone know how best to go about this?
I'm using angularjs 1.6.1 and I'm working on an internal system, so importing other scripts isn't really an option. Thanks for the help!
Here is an example turning both into components, you can leave the parent a controller if you wish. The thing most people find strange is having to send in an object for the parameters when using the '&' function binding. If you don't need to return parameters then that makes it easier :) Hope this helps.
Html:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>simple component example</title>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="myApp">
<parent-component></parent-component>
</div>
</body>
</html>
Javascript:
(function() {
'use strict';
angular
.module('myApp', [])
.component('parentComponent', {
controller: function() {
var ctrl = this;
ctrl.handleClick = function(id) { console.log(id) };
},
template: '<child-component click-me="$ctrl.handleClick(id)" greeting="hello"></child-component>'
})
.component('childComponent', {
bindings: { greeting: '@', clickMe: '&' },
template:`
<div>
<h1>{{$ctrl.greeting}}</h1>
<button ng-click="$ctrl.clickMe({id: '101010'})">Run Parent Function</button>
</div>
`,
controller: function() {
var ctrl = this;
console.log(this);
}
});
})();
Plunker Here
Updated Code to modify something in parent. Notice that I changed the greeting binding from a '@' (string literal) to a '<' (one way binding expression). Now the id sent back to the parent function will be appended to the greeting variable in the parent function, which is sent to the child for display. I have updated the plunker as well
(function() {
'use strict';
angular
.module('myApp', [])
.component('parentComponent', {
controller: function() {
var ctrl = this;
ctrl.greeting = 'hello';
ctrl.handleClick = function(id) { ctrl.greeting += id };
},
template: '<child-component click-me="$ctrl.handleClick(id)" greeting="$ctrl.greeting"></child-component>'
})
.component('childComponent', {
bindings: { greeting: '<', clickMe: '&' },
template:`
<div>
<h1>{{$ctrl.greeting}}</h1>
<button ng-click="$ctrl.clickMe({id: '101010'})">Run Parent Function</button>
</div>
`
});
})();