Reputation: 3675
My scenario, as shown in this jsfiddle: I have a directive which creates an empty iframe and attaches a load event which listens for clicks. On click calls scope.emitClick()
in the controller, which then uses socket.io to send a message to the backend server. Even though I am not sure this is the best way to do it, it works.
As it happens, I need to receive notifications from the backend server: the controller uses socket.io to listen for messages, and upon receiving a certain message it should be able to change the contents of the iframe created in the directive.
Is there a way to call a method defined in the directive from the controller? Is there a proper way to do something similar to what I am trying to accomplish?
html:
<div ng-controller="SimulationController">
<virtual-page id="testPage"/>
</div>
js:
var myModule = angular.module('myModule', []);
myModule.controller('SimulationController', function ($scope, socket) {
socket.on('update', function (data) {
//do something to iframe contents
});
$scope.emitClick = function (page, target) {
//socket.emit("click", { page: page, target: target });
console.log("clicked");
}
});
myModule.directive('virtualPage', function () {
var linkFn = function(scope, element, attrs) {
element.load(function () {
console.log(attrs.id + ": contents loaded");
jQuery(this).contents().off()
.on("click", function (event) {
console.log('>> clicked: ' + attrs.id + " - " + event.target);
scope.emitClick(attrs.id, event.target);
return false;
})
});
element[0].contentWindow.contents = "<html><head></head><body>test...</body></html>";
element[0].src = 'javascript:window["contents"]';
};
return {
restrict: 'E',
template: '<iframe src="about:blank"></iframe>',
replace: true,
link : linkFn
};
});
myModule.factory('socket', function () {
return {
on: function (eventName, callback) {
//fake
},
emit: function (eventName, data, callback) {
//fake
}
};
});
Upvotes: 0
Views: 352
Reputation: 8976
Modifying DOM in controller isn't an angular way IMHO. My approach to this kind problem would be:
In directive's linking function:
var linkFn = function(scope, element, attrs) {
...
scope.$watch('someData', function(newData) {
// change element according to the new data
});
};
In controller:
socket.on('update', function (data) {
$scope.someData = newData; // Update data, so directive can take action against it
});
Upvotes: 2