with - w3schools javascript window




Chame AngularJS do código legado (5)

A interoperabilidade de fora do angular para o angular é o mesmo que a depuração da aplicação angular ou a integração com a biblioteca de terceiros.

Para qualquer elemento DOM você pode fazer isso:

  • angular.element(domElement).scope() para obter o escopo atual do elemento
  • angular.element(domElement).injector() para obter o atual injetor de aplicativo
  • angular.element(domElement).controller() para se apossar da instância ng-controller .

A partir do injetor, você pode obter qualquer serviço em aplicação angular. Similarmente do escopo você pode invocar qualquer método que tenha sido publicado para ele.

Lembre-se de que quaisquer alterações no modelo angular ou em qualquer chamada de método no escopo precisam ser agrupadas em $apply() desta forma:

$scope.$apply(function(){
  // perform any model changes or method invocations here on angular app.
});

Eu estou usando o AngularJS para construir controles HTML que interagem com um aplicativo Flex legado. Todos os retornos de chamada do aplicativo Flex devem ser anexados à janela do DOM.

Por exemplo (em AS3)

ExternalInterface.call("save", data);

Chamará

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

De dentro da função de redimensionamento de JS, gostaria de despachar um evento que um controlador possa ouvir. Parece que criar um serviço é o caminho a percorrer. Você pode atualizar um serviço de fora do AngularJS? Um controlador pode escutar eventos de um serviço? Em um experimento (clique para violino) eu fiz parece que eu posso acessar um serviço, mas atualizar os dados do serviço não se reflete na visão (no exemplo um <option> deve ser adicionado ao <select> ).

Obrigado!


A maior explicação do conceito que encontrei está situada aqui: https://groups.google.com/forum/#!msg/angular/kqFrwiysgpA/eB9mNbQzcHwJ

Para poupar o clique:

// get Angular scope from the known DOM element
e = document.getElementById('myAngularApp');
scope = angular.element(e).scope();
// update the model with a wrap in $apply(fn) which will refresh the view for us
scope.$apply(function() {
    scope.controllerMethod(val);
}); 

Graças ao post anterior, posso atualizar meu modelo com um evento assíncrono.

<div id="control-panel" ng-controller="Filters">
    <ul>
        <li ng-repeat="filter in filters">
        <button type="submit" value="" class="filter_btn">{{filter.name}}</button>
        </li>
    </ul>
</div>

Eu declaro meu modelo

function Filters($scope) {
    $scope.filters = [];
}

E eu atualizo meu modelo fora do meu escopo

ws.onmessage = function (evt) {
    dictt = JSON.parse(evt.data);
    angular.element(document.getElementById('control-panel')).scope().$apply(function(scope){
        scope.filters = dictt.filters;
    });
};

Misko deu a resposta correta (obviamente), mas alguns novatos podem precisar de mais simplificação.

Quando se trata de chamar o código AngularJS de aplicativos herdados, pense no código AngularJS como um "micro aplicativo" existente em um contêiner protegido em seu aplicativo legado. Você não pode fazer chamadas diretamente (por uma boa razão), mas pode fazer chamadas remotas por meio do objeto $ scope.

Para usar o objeto $ scope, você precisa obter o identificador de $ scope. Felizmente isso é muito fácil de fazer.

Você pode usar o id de qualquer elemento HTML em seu HTML "micro-app" AngularJS para obter o identificador do escopo $ angularJS app.

Como exemplo, digamos que queremos chamar algumas funções dentro do nosso controlador AngularJS, como sayHi () e sayBye (). No AngularJS HTML (view) temos um div com o id "MySuperAwesomeApp". Você pode usar o seguinte código, combinado com jQuery para obter o identificador de $ scope:

var microappscope = angular.element($("#MySuperAwesomeApp")).scope();

Agora você pode chamar suas funções de código AngularJS por meio do identificador de escopo:

// we are in legacy code land here...

microappscope.sayHi();

microappscope.sayBye();

Para tornar as coisas mais convenientes, você pode usar uma função para pegar a alça de escopo sempre que quiser acessá-la:

function microappscope(){

    return angular.element($("#MySuperAwesomeApp")).scope();

}

Suas chamadas ficariam assim:

microappscope().sayHi();

microappscope().sayBye();

Você pode ver um exemplo de trabalho aqui:

http://jsfiddle.net/peterdrinnan/2nPnB/16/

Eu também mostrei isso em uma apresentação de slides para o grupo Ottawa AngularJS (apenas pule para os dois últimos slides)

http://www.slideshare.net/peterdrinnan/angular-for-legacyapps


Eu sei que esta é uma pergunta antiga, mas eu estava olhando para opções para fazer isso recentemente, então eu pensei em colocar minhas descobertas aqui caso seja útil para qualquer um.

Na maioria dos casos, se houver necessidade de código herdado externo interagir com o estado da interface do usuário ou com o funcionamento interno do aplicativo, um serviço poderá ser útil para abstrair essas alterações. Se um código externo estiver interagindo diretamente com seu controlador, componente ou diretiva angular, você estará acoplando intensamente seu aplicativo ao seu código herdado, o que é uma má notícia.

O que acabei usando no meu caso, é uma combinação de globals acessíveis pelo navegador (por exemplo, janela) e manipulação de eventos. Meu código tem um mecanismo de geração de formulário inteligente que requer saída JSON de um CMS para iniciar os formulários. Aqui está o que eu fiz:

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 ....

O Serviço de Esquema de Formulário é criado usando o injetor angular conforme o esperado:

angular.module('myApp.services').
service('FormSchemaService', ['$window' , FormSchemaService ])

E nos meus 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(); 

Até agora, isso é pura programação orientada a serviços angular e javascript. Mas a integração legada vem aqui:

<script type="text/javascript">

   (function(app){
        var conf = app.conf = {
       'fields': {
          'field1: { // field configuration }
        }
     } ; 

     app.dispatchEvent(new Event('register-schema'));

 })(window);
</script>

Obviamente, toda abordagem tem seus méritos e desvantagens. As vantagens e o uso dessa abordagem dependem da sua interface do usuário. As abordagens sugeridas anteriormente não funcionam no meu caso, pois meu esquema de formulário e código legado não têm controle e conhecimento de escopos angulares. Daí configurar meu aplicativo com base em angular.element('element-X').scope(); potencialmente poderia quebrar o aplicativo se mudarmos os escopos ao redor. Mas se o seu aplicativo tiver conhecimento do escopo e puder confiar que ele não está mudando com frequência, o que é sugerido anteriormente é uma abordagem viável.

Espero que isto ajude. Qualquer feedback também é bem-vindo.





angularjs