2015-04-25 52 views
0

我想创建一个指令,该指令可以使用AngularJS的递归树结构,其中每个节点都可以在transclude部分中有自己的模板。无法替换ng模板中的元素

这里是JS:

var app = angular.module('plunker', []); 
app.controller('MainCtrl', function($scope) { 
    $scope.input = [{ 
    name: 'blueberry cheesecake', 
    color: 'blue', 
    children: [{ 
     name: 'blueberry cheesecake', 
     color: 'blue' 
    }, { 
     name: 'rocky road', 
     color: 'mostly brown' 
    }] 
    }, { 
    name: 'rocky road', 
    color: 'mostly brown' 
    }]; 
}); 
app.directive("auratree", function() { 
    return { 
    scope: { 
     input: "=" 
    }, 
    template: function(element) { 
     element.data("customListTemplate", element.find("item-template")); 
     var c = 
     '<script type="text/ng-template" id="auratree2">' + 
     '<item-placeholder></item-placeholder>' + 
     '  <div ng-if="item.children">' + 
     '   <div ng-repeat="item in item.children" ng-include="' + 
     "'" + 'auratree2' + "'" + '">' + 
     '   <item-placeholder></item-placeholder></div>' + 
     '  </div>' + 
     '</script>' + 
     '<div ng-repeat="item in input" ng-include = "' + "'" + 'auratree2' + "'" + '">' + 
     '</div>'; 
     console.log(c); 
     return c; 
    }, 
    compile: function(tElement, tAttrs) { 
     var template = tElement.data("customListTemplate"); 
     tElement.find("script").html(tElement.find("script").html().replace("<item- placeholder></item-placeholder>", template.html())); 
    } 
    }; 

    function link(scope, element, attrs) {} 
}); 

下面是HTML

<!DOCTYPE html> 
<html ng-app="plunker"> 
    <head> 
    <meta charset="utf-8" /> 
    <title>Aura Tree</title> 
    <script>document.write('<base href="' + document.location + '" />');</script> 
    <script data-require="[email protected]" src="https://code.angularjs.org/1.3.13/angular.js" data-semver="1.3.13"></script> 
    <script src="auratree.js"></script> 
    </head> 
<body ng-controller="MainCtrl"> 
    <pre>template 1:</pre> 
    <auratree input="input"> <item-template> 
    {{$index}} | {{item.name}} 
    <hr> 
    </item-template> </auratree> 
</body> 
</html> 

此代码

tElement.find("script") 
    .html(tElement.find("script").html() 
    .replace("<item-placeholder></item-placeholder>",template.html())); 

在Chrome的工作,但不是在IE11工作。

通常element.replaceWith不工作,所以我试图改变html ...但不成功。

请告诉我解决方案来克服这个问题。

这里是plunker

回答

1

我不认为你的方法与ng-template一样按你期望的方式工作。即使您设法替换ng-template中的占位符,但如果应用中有多个<auratree>元素,每个元素都有不同的项目模板,则所有模板都将具有相同的(最后编译的)模板。

使用ng-include是一个聪明的技巧,但这个问题有点复杂。而不是依靠ng-include d模板,在每个级别包含相同的指令link-时间(这是什么ng-include会做什么),并使用transcludeitem-template

因为每个子树(其具有的值,并children)一个根元素之间的一些非对称性(其仅具有项目的阵列),以及我添加另一指令来表示每个树项:

的根指令只重复每个项目,并transcludes的item-template

app.directive("tree", function(){ 
    return { 
    restrict: "E", 
    scope: { 
     items: "=" 
    }, 
    transclude: true, 
    template: '<div ng-repeat="item in items">\ 
       <tree-item item="item"></tree-item>\ 
       </div>', 
    link: function(scope){ 
     scope.$level = -1; 
    } 
    }; 
}); 

treeItem指令transcludes从父item-template,并重复子项,如果有的话:

app.directive("treeItem", function($compile){ 
    return { 
    scope: { 
     item: "=" 
    }, 
    link: function(scope, element, attrs, ctrls, transclude){ 
     scope.$index = scope.$parent.$index; 
     scope.$level = scope.$parent.$level + 1; 

     transclude(scope, function(clone){ 
     element.append(clone.contents()); 
     var repeater = angular.element('<div ng-repeat="child in item.children">'); 
     var subtree = angular.element('<tree-item item="child">'); 

     element.append(repeater.append(subtree)); 

     $compile(repeater)(scope, null, { parentBoundTranscludeFn: transclude }); 
     }); 
    } 
    }; 
}); 

用法是:

<tree items="items"> 
    <item-template> 
    {{$level}}.{{$index}} | {{item.v}} 
    </item-template> 
</tree> 

Demo

0

最好把该模板的角度$templateCache里面的角&运行阶段,从指令中删除该模板

运行阻滞

app.run(function($templateCache) { 

    $templateCache.put('auratree2', '<item-placeholder></item-placeholder>' + 
     '  <div ng-if="item.children">' + 
     '   <div ng-repeat="item in item.children" ng-include="' + 
     "'" + 'auratree2' + "'" + '">' + 
     '   <item-placeholder></item-placeholder></div>' + 
     '  </div>' 
    ); 
}); 

指令(模板功能)

template: function(element){  
    element.data("customListTemplate", element.find("item-template")); 
    var c= '<div ng-repeat="item in input" ng-include = "' + "'" +'auratree2' + "'"+ '"></div>'; 
    return c; 
}, 
+1

不工作.. BTW模板已被缓存..但我想更换使用replaceWith像** tElement占位符的内容.find(“item-placeholder”)。replaceWith(template.contents()); ** –

-1

你的plunkr有JQuery,但是你的StackOverflow问题没有,所以我假设你正在使用JQuery(你可能必须因为JQLite的限制)。

在您的HTML文件中,修改JQuery和Angular的顺序,使前者列在第一位。

<head> 
    <meta charset="utf-8" /> 
    <title>Aura Tree</title> 
    <script>document.write('<base href="' + document.location + '" />');</script> 
    <script data-require="[email protected]*" data-semver="2.1.3" src="http://code.jquery.com/jquery-2.1.3.min.js"></script> 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script> 
    <script src="script.js"></script> 
    </head> 
+0

我想我可能在plunker中添加了jQuery错误,我没有使用jQuery ... –