如何强制angular从自定义指令渲染外部元素?

时间:2014-07-15 11:43:13

标签: angularjs

我需要在angularjs中提供一些帮助, 请看看这个 代码(chrome浏览器):

http://jsfiddle.net/Aravind00kumar/CrJn3/

<div ng-controller="mainCtrl">
    <ul id="names">
        <li ng-repeat="item in Items track by $index">{{item.name}} </li>
    </ul>

    <ak-test items="Items">

    </ak-test>
</br>
    <div id="result">

    </div>
</div>


    var app = angular.module("app",[]);
    app.controller("mainCtrl",["$scope",function($scope){
        $scope.Items = [
            {name:"Aravind",company:"foo"},
            {name:"Andy",company:"ts"},
            {name:"Lori",company:"ts"},
            {name:"Royce",company:"ts"},
        ];
        $scope.Title = "Main";

    }]);

app.directive("akTest",["$compile",function($compile){
    return {
        restrict: 'E',
        replace: true,
        scope: {
            items: "="
        },
        link: function (scope, element, attrs) {
//            var e =$compile('<li ng-repeat="item in Items track by $index">{{item.name}} </li>')(scope);
//            $("#names").append(e);

            var lilength = $("#names li").length;
            var html ='<div> from angular ak-test directive: '+lilength+'</div>';
            element.replaceWith(html);
        }
    };
}]);
        $(function(){
            $("#result").html('from jquery:  '+$("#names li").length);
        });

我创建了一个自定义指令,并尝试从视图中访问一个元素,该元素位于我的自定义指令上方的ng-repeat中 问题是,在指令中它说ng-repeat还没有呈现。 这是问题所在 我有两个要素

<svg>
<g>
List of elements
</g>
<g>

Based on the above rendered elements I have to draw a line between elements like a connection. I have to wait till the above elements to get render then only I can read the x,y positions and can draw a line.
</g>
</svg>   

元素和连接都是范围变量。根据我的理解,两者都在相同的范围内,执行流程从父到子开始,从子到父完成。在启动自定义指令之前,如何强制完成ng-repeat渲染部分?

是否有任何角度来替代这种依赖?

3 个答案:

答案 0 :(得分:0)

已经有一段时间了,所以我的Angular有点生疏了。但是,如果我正确理解你的问题,那就是我遇到过几次问题。您似乎希望延迟处理标记的某些元素,直到其他元素完全呈现为止。您可以选择以下几种方法:

您可以使用超时等待页面呈现:

$timeout(function() {
    // do some work here after page loads
}, 0);

这通常可以正常工作,但可能会导致您的页面不愉快地闪烁。

您可以使用$ evalAsync在以后的摘要周期中渲染部分代码:

这个主题有一篇很好的帖子:AngularJS : $evalAsync vs $timeout。通常情况下,我更喜欢这个选项,因为它没有遭受同一页面闪烁问题。

或者,您可以寻找重构指令的方法,以便相关部分不会如此孤立。该选项是否有用将取决于您的应用程序的更大背景以及您希望这些部分的可重用性。

希望有所帮助!

答案 1 :(得分:0)

我会为整个列表创建一个指令,也许是每个列表项的嵌套指令。那会让你有更多的控制权。

答案 2 :(得分:0)

非常感谢您的快速回复#Royce#Lori

我发现这个问题是因为ng-repeat导致我用以下方式解决了它。

  1. 为列表元素创建自定义指令,并在另一个指令启动之前在for循环中呈现所有元素。这个修复程序暂时解决了这个问题,但我也会尝试$ evalAsync和$ timeout:)

        var app = angular.module("app",[]);
    app.controller("mainCtrl",["$scope",function($scope){
    $scope.Items = [
        {name:"Aravind",company:"foo"},
        {name:"Andy",company:"ts"},
        {name:"Lori",company:"ts"},
        {name:"Royce",company:"ts"},
    ];
    $scope.Title = "Main";
    
    }]);
    
    app.directive("akList",["$compile",function($compile){
    return {
    restrict: 'A',
    replace : false, 
    link: function (scope, element, attrs) {
      var _renderListItems = function(){
        $(element).empty();  
        for(var i=0;i<scope.Items.length; i++)
          {
            var li ='<li> '+ scope.Items[i].name +' </li>';
           element.append(li);
          }
        };
      _renderListItems(scope);
      scope.$watch('Items.length', function (o, n) {
            _renderListItems(scope);
        }, true);
    }};}]);
    
    app.directive("akTest",["$compile",function($compile){
    return {
    restrict: 'E',
    replace: true,
    scope: {
        items: "="
    },
    link: function (scope, element, attrs) {
        var lilength = $("#names li").length;
        var html ='<div> from angular ak-test directive: '+lilength+'</div>';
        element.replaceWith(html);
    }
    };
    }]);
    $(function(){
        $("#result").html('from jquery:  '+$("#names li").length);
    });