I have to add an third party JavaScript plugin with callback function to an Angular JS application.
The JavaScript plugin provides a function like this:
thirdPartyFunction(parameter1, parameter2, parameter3, callback);
In the callback function I get the result that the plugin calculated.
The callback function looks like this:
callback(resultobject)
{ ... }
I want to display the result in my angular application. How can I get the resultobject in the $scope? It's not possible to rewrite the JavaScript plugin so far.
My idea is to provide a angular service like this one, but how should I implement the service?:
app.factory('myservice', function () {
function callback(resultobject) {
???
}
return {
getResult: function(parameter1, parameter2, parameter3) {
thirdPartyFunction(parameter1, parameter2, parameter3, callback);
return ???;
}
};
});
Service may not help here. Look at angular directives here. Depending on how the plugin is integrated on the page you would have to create a directive that exposes the plugin functionality.
Directives create their own scopes and can broadcast \ emit messages that can be channeled to controllers where you can update the model, on plugin callback and call $scope.apply() which would then refresh the UI
If you can reference the plugin in Controller directly then the only thing you would need to do after the async callback would be to update the model and call $scope.apply()
Let's assume your controller has some model you want the plugin to eventually update:
$scope.model = { prop1: 'plugin will update this value' };
As @Chandermani already suggested, define a directive. In the linking function, define the callback function. When the callback is called, because of the closure we created, it will have access to the directive's scope.
You have quite a bit of freedom with repect to the directive scope. You can use the same scope as the parent (this is what directives do by default) and directly update scope.model.prop1. You can create a new scope (scope: true) and still have access to scope.model.* via prototypal inheritance. You can create an isolate scope (scope: { ... }) and use the '=' syntax to bind a property to the parent scope.
app.directive('somePlugin', function() {
return {
scope: true,
link: function(scope, element, attrs) {
// define the callback here
function callback(resultObject) {
scope.model.prop1 = resultObject.propx;
scope.$apply(); // let Angular know about the change we just made
}
// initialize the plugin here
thirdPartyFunction(parameter1, parameter2, parameter3, callback);
// do other directive stuff here
// ...
}
}
});
First of all, thank you for your reply. Now, here is my solution how to call the function "thirdPartyFunction" whenever you want. Just change a variable in your scope.
app.directive('somePlugin', function() {
return {
scope: true,
link: function(scope, element, attrs) {
function callback(resultObject) {
scope.model.prop1 = resultObject.propx;
scope.model.state = "waiting";
scope.$apply();
}
scope.$watch('model.state', function(newValue, oldValue) {
if (newValue == "request") {
thirdPartyFunction(scope.model.parameter1, scope.model.parameter2,
scope.model.parameter3, callback);
}
});
}
}
});