Call AngularJS from legacy code

2018-12-31 21:02发布

I'm using AngularJS to build HTML controls that interact with a legacy Flex application. All callbacks from the Flex app must be attached to the DOM window.

For example (in AS3)

ExternalInterface.call("save", data);

Will call

window.save = function(data){
    // want to update a service 
    // or dispatch an event here...
}

From within the JS resize function I'd like to dispatch an event that a controller can hear. It seems that creating a service is the way to go. Can you update a service from outside of AngularJS? Can a controller listen for events from a service? In one experiment (click for fiddle) I did it seems like I can access a service but updating the service's data doesn't get reflected in the view (in the example an <option> should be added to the <select>).

Thanks!

7条回答
荒废的爱情
2楼-- · 2018-12-31 21:59

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.

查看更多
登录 后发表回答