Манипулировать DOM после того, как Angular извлек контент через $http и добавил его в шаблон частичного представления

Я рассмотрел различные похожие вопросы, такие как этот, этот, этот, этот и этот, который не смог найти решение моей проблемы до того, как сам нашел решение. Тем не менее, это все еще не похоже на «правильный» путь Angular, поэтому я прошу совета у сообщества.

Вот установка. У меня есть шаблон макета (index.html):

<!DOCTYPE html>
<html ng-app="app">    
<head>
    ...
</head>
<body role="document">
    <div id="wrapper" class="container" role="main" ng-controller="mainController">

        <div id="header">
            ...
        </div>

        <div id="diagram" ng-view="ng-view"></div>

        <div id="footer>
            ...
        </div>

        <script>
            ...
        </script>

    </div>
</body>
</html>

У меня есть шаблон частичного представления (diagram.html). Обратите внимание на пользовательскую директиву, описанную ниже:

<div my-diagram ng-bind-html="diagram"></div>

Вот моя конфигурация маршрутизации с указанием шаблона частичного представления и контроллера:

angular.module("app", ["ngRoute", "ngSanitize", "controllers", "directives"])
    .config(["$routeProvider",
        function ($routeProvider) {
            $routeProvider
                .when("/process/:processId", {
                    templateUrl: "diagram.html",
                    controller: "processDiagramController"
                });

        }]);

Вот контроллер, используемый для частичного представления. Он использует значение processId из $routeParams, чтобы сделать вызов через $http.get() для получения данных SVG, которые он присваивает $scope.diagram, привязанному к шаблону:

angular.module("controllers")
    .controller("processDiagramController", ["$scope", "$http", "$routeParams", "$sce",
        function ($scope, $http, $routeParams, $sce) {

            var onError = function (response) {
                $scope.errors.push(response.data);
            }

            var onDiagram = function (response) {
                $scope.diagram = $sce.trustAsHtml(response.data);
            }

            $scope.errors = [];

            $http.get("/" + $routeParams.processId + ".svg").then(onDiagram, onError);

        }
    ]);

Моя проблема заключалась в том, чтобы выяснить, как запускать код в SVG-контенте после его добавления в DOM. Конечно, правильное место для любых манипуляций с DOM в Angular — это директива, поэтому я написал ее:

angular.module("directives", [])
    .directive("myDiagram", function () {
        return {
            link: function(scope, element, attrs) {
                scope.$watch(function() {
                    return element.html();
                },
                function () {
                    diagram.process(element);
                });
            }
        };
    });

Единственный способ, которым я мог заставить функцию chart.process() запускаться ПОСЛЕ того, как содержимое SVG было добавлено в DOM, — это использовать $watch для element.html(), как показано. Это то, что мне кажется «неправильным», и я хотел бы знать, есть ли более «правильный» способ.


person jgolieb    schedule 02.10.2014    source источник
comment
Почему вы не можете поставить часы на $scope.diagram в директиве, а затем вызвать diagram.process(element). Возможно, вам придется обернуть вызов в $timeout.   -  person Chandermani    schedule 02.10.2014
comment
Я пробовал смотреть $scope.diagram. Это не сработало ни с использованием $timeout, ни без него. Код всегда выполнялся до заполнения элемента.   -  person jgolieb    schedule 02.10.2014