如何在AngularJs指令与ngRepeat配对后有条件地插入HTML?

时间:2013-07-09 00:52:48

标签: angularjs angularjs-directive angularjs-ng-repeat

=================

首先,我只想说我是AngularJs业务的新手(今天早些时候开始),我可能会使事情变得复杂。

说实话,让我们开始做生意,不是吗?

我有以下jsFiddle,html输出如下。

<div ng-app="test" ng-controller="About" class="hex-grid clearfix ng-scope">
    <div class="hex odd" ng-repeat="person in ledning">
        <a href="">
           <div class="inner">
               <h3 class="ng-binding">Just a name</h3>
               <hr class="grid-1 center">
               <p class="ng-binding">a title</p>
           </div>
           <div class="hex-1">
               <span class="after"></span>
           </div>
           <div class="hex-2">
               <span class="after"></span>
           </div>
           <span class="after"></span>
        </a>
    </div>
   <!-- and 5 times more -->
</div>

现在,我想要实现的是这个 - &gt; http://jsfiddle.net/engstrumpan/yCv79/4/embedded/result/

这只是简单的html(没有AngularJs)只是为了展示我想要实现的目标。通过在六边形 3 5 之后插入<br />来实现此特定布局

想象一下,如果我想要这样的布局

 1 1 1                1
1 1 1 1   or even    1 1
 1 1 1              1 1 1
                   1 1 1 1
                    1 1 1
                     1 1
                      1

如何实现这一目标? 该指令多次使用,因此我希望它尽可能通用。

到目前为止我尝试的是以下

var app = angular.module('test', []);
app.controller('About', function ($scope) {
    $scope.ledning = [
      {
        ...
        shouldBreak: true
      }
});
app.directive('hexagon', function () {
    var tmpl = '<div>
                   <!-- directive template snippet -->
                </div>
                <br ng-show="{{data.shouldBreak}}" />';

  // rest  of code
});

由于AngularJs使用以下消息<br ng-show="{{data.shouldBreak}}" />

抛出异常,因此Template must have exactly one root element.无效

同样在指令上弄乱compile,但只会在最后一次迭代后插入<br />(转发器完成工作后)< / p>

var app = angular.module('test', []);
app.directive('hexagon', function () {
   return { 
     ...
     compile: function($scope, el, attrs){
        return function ($scope, el, attrs){
            if($scope.data.shouldBreak !== undefined){
                el.after('<br />');
            }
        };
     }
    }
});

在谈到指令时我已经阅读了文档,要么我只是愚蠢,要么我错过了显而易见的,所以请帮帮我。

墙上文字的结束,也许有些睡眠就可以了。明天再回头看马吧。

2 个答案:

答案 0 :(得分:2)

所以我在离开几天后成功找到了解决办法,然后当我回到城镇时,我再次解决了我的问题。

解决方案

视图

<hexagon ng-repeat="person in ledning" data="person" layout="layout"></hexagon>

控制器:

var app = angular.module('test', []);
app.controller('About', function ($scope) {
    ...
    $scope.layout = [2,4]; // what index (inside ngRepeat) should we break on

}

});

和指令

app.directive('hexagon', function ($timeout) {
...
return {
    ...
    scope: {
        data: '=',
        layout: '=' // grab the data bound to 'layout'
    },
    link: function ($scope, el, attrs) {
        $timeout(function(){
            for (var i = 0; i < $scope.layout.length; i++) {

                        if ($scope.layout[i] == $scope.$parent.$index)
                            el.after('<br />');
                    }
        }, 0);
    }
};

});

这里可以看到一个工作示例http://jsfiddle.net/engstrumpan/yCv79/5/

因此,如果我使用10个项目,我可以设置$scope.layout = [2,6]以获得此jsFiddle

中的以下输出

那么我是如何最终得到这个解决方案的呢?好吧,我要感谢这个人(Lorenz Merdian)和他的博客。至少当使用$timeout来给浏览器足够的时间来渲染元素的DOM以便我可以插入我的<br />

它可能不是最优雅的解决方案,但在这种特殊情况下它适用于我

答案 1 :(得分:1)

您可以使用伪类在"\a"之前或:before之后插入回车:after(尽管如果您支持旧浏览器,这不适合您)。

CSS:

.last:before {
    content: "\A";
    white-space:pre;
} 

条件ng-class设置换行类,其中item.lineBreak包含truefalse,具体取决于其在组中的顺序:

ng-class="{last:item.lineBreak}"

这是基本答案,here's the working plunk在元素上使用ng-class。

在模板的根元素上使用ng-class

Fork of the plunk。结果相同。

...


...

棘手/有趣的部分能够动态地将该类/伪类插入到正确的元素中而无需对其进行硬编码。看起来你想要一个金字塔(Fibonacci wannabe)设计(这个问题看起来很有趣)。

我所做的是使用一个非常基本的循环过程将true属性 - (从上面的例子item.lineBreak)插入到第1,第3,第6,第10的项目中(以及ng-repeat中的项目。我把它放在选择框模型的$watch中,这样你就可以选择组中的项目数。

这是$ watch和

var findFib = function(index){

if(index==increment){
  rowLength += 1;
  increment = rowLength + increment;
  return true;
}   

return false;
}

$scope.$watch('collectionAmount.value', function(val){
    $scope.collection = [];
    rowLength = 1;
    increment = 1;
    var i = 1;

    //loop through the items, using the Fibonacci-like
    //method to determine which items will recieve the 
    //lineBreak property of true;
    while(i<=val){
      var f = findFib(i);
      $scope.collection.push({number: i, lineBreak: f});
      console.log($scope.collection[i-1]);
      i++;      
    }
    //reverse the array if using :before pseudoclass to get upside-down pyramid:
    $scope.collection.reverse();
  })

从那里开始,ng-class有条件地应用了.last类,其中包含插入返回的:before伪类。这可以很容易地缩放以适应您更复杂的标记。