david wendelken david wendelken - 23 days ago 22
AngularJS Question

Angular 1.5 Non-Parent Component to Component Communication

I'm trying to do something simple.

I have a component called sender that wants to send a message to a non-child component called receiver. Sender finds the receiver component and changes its attribute value.

Unfortunately, the receiver component doesn't recognize that it's attribute has been changed.

When this is done, there will be multiple sending components that will make use of the same receiving component instance, so I don't want to make it a child component.

How do I get the receiving component to recognize it has a new attribute value?

Here's a plunkr

HTML:

<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js@1.5.8" data-semver="1.5.8"
src="https://code.angularjs.org/1.5.8/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="https://code.angularjs.org/1.5.8/angular.js"></script>
</head>
<body>
<h1>Test sending values to a component from a non-parent component</h1>
<sender id="SendingComponent"></sender>
<h2>past send tag</h2>
<receiver id="ToComponent" textvalue="defaultvalue"></receiver>
<h2>Past receiver tag</h2>
<script src="script.js"></script>
</body>
</html>


Javascript:

var app = angular.module('app',[])
.component("sender", {
template: "<div> I send messages to receiver.
Receiver should say 'a new sent value'.</div>",
controller: [function () {
var ctrl = this;
ctrl.$oninit = function () {
var receiver = document.getElementById('ToComponent');
receiver.attributes.setNamedItem('textvalue', 'a new sent value');
$timeout(function () { $scope.apply();});
};
}]})
.component("receiver", {
template: '<div>I received this message:
{{receiverCtrl.textvalue}}</div>',
bindings: {
textvalue: '<' // using '@' makes the default value work,
// but is described as a one time bind
},
controllerAs: 'receiverCtrl',
controller: [function () {
var ctrl = this;
ctrl.$onChanges = function (changesObj) {
if (changesObj.textvalue !== undefined) {
ctrl.textvalue = changesObj.textvalue.currentValue;
}
}
}]
});

angular.bootstrap(document, ['app']);

Answer

Sounds to me like you should be working with events instead. Maybe your senders would $broadcast the value to be changed, and your receiver would listen to that event and do whatever needs to be done with the value.

This also has the advantage of your senders not needing to manipulate the DOM to send their message. This way, you'd leave DOM manipulation to the receiver only, if necessary.

Comments