I know this is an old question but I was looking at options to do this recently, so I thought I put my findings here in case it's useful to anyone.
In most cases, if there's the need for external legacy code to interact with the state of the UI or the inner workings of the application a service could be useful to abstract away those changes. If an external code is interacting directly with your angular controller, component or directive, you're coupling your app heavily with your legacy code which is bad news.
What I ended up using in my case, is a combination of browser accessible globals (i.e. window ) and event handling. My code has a smart form generation engine which requires JSON output from a CMS to initiliase the forms. Here's what I have done :
function FormSchemaService(DOM) {
var conf = DOM.conf;
// This event is the point of integration from Legacy Code
DOM.addEventListener('register-schema', function (e) {
registerSchema(DOM.conf);
}, false);
// service logic continues ....
Form Schema Service is created using angular injector as expected:
angular.module('myApp.services').
service('FormSchemaService', ['$window' , FormSchemaService ])
And in my controllers:
function () {
'use strict';
angular.module('myApp').controller('MyController', MyController);
MyEncapsulatorController.$inject = ['$scope', 'FormSchemaService'];
function MyController($scope, formSchemaService) {
// using the already configured formSchemaService
formSchemaService.buildForm();
So far this is pure angular and javascript service oriented programming. But the legacy integration comes here :
<script type="text/javascript">
(function(app){
var conf = app.conf = {
'fields': {
'field1: { // field configuration }
}
} ;
app.dispatchEvent(new Event('register-schema'));
})(window);
</script>
Obviously every approach has it's merits and drawbacks. The advantages and use of this approach depends on your UI. The previously suggested approaches don't work in my case since my form schema and legacy code have no control and knowledge of angular scopes. Hence configuring my app based on angular.element('element-X').scope();
could potentially break the app if we change the scopes around. But if you're app has knowledge of the scoping and can rely on it not changing often, what's suggested previously is a viable approach.
Hope this helps. Any feedback is also welcome.
var injector = angular.injector(['ng', 'MyApp']);
. Doing this will give you a completely new context and a duplicatemyService
. That means you'll end up with two instances of the service and model and will be adding data to the wrong place. You should instead target an element within the app usingangular.element('#ng-app').injector(['ng', 'MyApp'])
. At this point you can then use $apply to wrap model changes. – Thanh Nguyen