The best solution is to move $scope.isActive to a new 'root' component that contains both 'component A' and 'component B'.
Then you can pass / modify its value using input/output bindings in the 'component A' and 'component B' definitions like:
component A definition:
angular.module('app').component('componentA', {
templateUrl: 'component-A.html',
bindings: {
isActive: "<", // use to bind property as component input
isActiveChanged: "&" // use to bind a METHOD that changes the property in the root component controller
}
});
component A template (component-A.html):
<img
src="res/large-loading.gif"
ng-if="!$ctrl.isActive"
ng-click="$ctrl.isActiveChanged({isActive: !$ctrl.isActive})"/>
component B definition:
angular.module('app').component('componentB', {
template: 'component-B.html',
bindings: {
isActive: "<", // use to bind property as component input
isActiveChanged: "&" // use to bind a METHOD that changes the property in the root component controller
}
});
component B template (component-B.html):
<img
src="res/large-loading.gif"
ng-if="!$ctrl.isActive"
ng-click="$ctrl.isActiveChanged({isActive: !$ctrl.isActive})"/>
root component definition:
angular.module('app').component('root', {
templateUrl: 'root-component-view.html', ,
controller: 'RootComponentCtrl'
});
root component controller:
angular.module('app').controller('RootComponentCtrl', ['$scope', function($scope) {
// INPUT: This property is shared with both 'component A' and 'component B'
$scope.isActive = true;
// OUTPUT: This method is shared with both 'component A' and 'component B' and can be called from both in order to change the value of $scope.isActive in the RootComponentCtrl
$scope.isActiveChanged(isActive) {
$scope.isActive = isActive;
};
}]);
root-component-view.html template:
<div>
<component-a
is-active="isActive"
is-active-changed="isActiveChanged(isActive)"
></component-a>
<component-b
is-active="isActive"
is-active-changed="isActiveChanged(isActive)"
></component-b>
</div>
Notice that binded properties are accessed in the component view/template using the '$ctrl' object like '$ctrl.isActive' as opposed to simply using 'isActive' which refers to the component's $scope.isActive property in the component controller.
To resume:
The shared property is set in the root component controller using:
$scope.isActive = true;
The shared property can be seen in the root component template using:
...>some html text content plus this is {{isActive}}<...
The shared property is passed to componentA and componentB in the html that defines them in the root component view using:
<component-a
is-active="isActive"
is-active-changed="isActiveChanged(isActive)"
></component-a>
<component-b
is-active="isActive"
is-active-changed="isActiveChanged(isActive)"
></component-b>
The shared property is visible in componentA / componentB templates using:
...>some html text content plus this is {{$ctrl.isActive}}<...
The shared property is visible in componentA / componentB controllers using:
this.isActive // not $scope.isActive
The shared property can be changed from componentA / componentB controllers by calling the method:
$ctrl.isActiveChanged({data: data})
Which actually will call the method in the root component controller and pass the updated value to the $scope property:
$scope.isActiveChanged(data)