仅当页面的某个部分发生更改时才运行angular compile

时间:2015-01-14 22:46:32

标签: javascript jquery html ajax angularjs

所以我正在开发一个应用程序,它有许多通过jquery ajax加载的部分,一些在启动时有些,另一些在响应其他部分,有些甚至是嵌套的。我不能做的是说“哦,mainContainer中的内容发生了变化?”好吧,去编译那部分的代码。

原因是我希望能够将ui-sref放入我们原本不想搞砸的部分代码中。我提出了一个解决方案,但它没有像我想象的那样工作,我在一个自定义指令中添加了一个$watch,但它发射了数十亿次。这是代码。

希望有人可以解释如何只有当X <div>中的内容通过发生的许多ajax调用之一被更改时才能运行一次,这样我就不需要立即转换所有将旧代码转换为angular并且可以链接到使用angular的新代码。

app.directive('ngMainContainer', function ($compile, $timeout) {
    console.log("main container directive");
    return function (scope, elem, attrs) {
        scope.$watch(function () {
            return elem;
        }, function (val) {
            console.log("Something changed. " + val);
            $timeout(function () {
                $compile(val)(scope);
            }, 0);
        });
    };
});

再一次,我认为对传递给指令的元素进行监视就是答案,但是当我移动鼠标并点击通过jquery ajax加载的容器外部某处的页面时,它仍会运行。

2 个答案:

答案 0 :(得分:1)

这是一个可能适合您的解决方案。我将指令ngMainContainer放在我们想要观察html内容的元素上。

在我们的控制器中,我首先<p>{{ content }}</p>附加$compile,然后像var更新范围$scope.html = angular.element(myDiv).html()。这是我们的指令$watch触发的地方。

这是完整的工作示例。 <button>附加了html,但这应该模拟完成ajax调用请求的解析。

JSFiddle Link

app.directive('ngMainContainer', [function () {
    return {
        restrict: 'A',
        link: function (scope, elem, attrs) {

            scope.$watch('html', function(n, o) {
                if(n !== o) {
                    console.log(elem.contents())
                    // html has changed, do something!
                }
            });
        }
    }
}]);


app.controller('ctrl', ['$scope', '$compile', function($scope, $compile) {

    $scope.content = "scope content";

    var myDiv = document.getElementById('main');

    $scope.appendContent = function() { // Replicate Ajax Callback

        var dynamic = $compile('<p ng-cloak>{{ content }}</p>')($scope); // Compile content        
        angular.element(myDiv).append(dynamic);
        $scope.html = angular.element(myDiv).html()
    }
}]);

修改

这是一种在将内容附加到<div>时执行此操作的方法,而在执行附加的代码上没有角度概念

Updated JSFiddle

<button id="noAngular" onclick="noAngularAppend()">Append Content - No Angular</button>


function noAngularAppend() {
    angular.element(document.getElementById('main')).scope().externallyAppend('<p ng-cloak>{{ content }}</p>');
}


指令功能(注入$compile

scope.externallyAppend = function(element) {
    var node = $compile(element)(scope);
    elem.append(node);
    scope.$apply(scope.html = elem.contents());
}

答案 1 :(得分:0)

萨尔,我投了你的答案,因为它最终帮助我解决了这个问题,但最终它并不是我想要的。

这就是我最终的结果。在主应用程序的控制器中,只有两行功能。

 $scope.doReshing = function (element) {
    $compile(angular.element(element))($scope);
    $scope.$apply();
}

然后在document.ready()的顶部有一个ng指令的部分,我把它放在下面。

 var removeableContentContainer = $('#removableContentContainer');
 angular.element(removeableContentContainer).scope().doReshing(removeableContentContainer);

这正是我想要的。它让我对现有的应用程序几乎没有任何关于它如何工作的改变,并允许我在&#34; old&#34;中添加ui-srefs。代码而不必担心加载的方式或时间,当它加载时,document.ready()会触发,它会告诉angular它需要编译。这是我的目标,你可以在任何时间点拉出一些代码,让它们基本上就好像它们是那个页面的一部分一样,带有它的控制器。