代码之家  ›  专栏  ›  技术社区  ›  andimeier

角度方向操纵ng使用全局开关重复项目

  •  1
  • andimeier  · 技术社区  · 9 年前

    所以,我的脑海中有一个这样的画面:

    新指令 compactList 适用于包含 ngRepeat 指令,执行以下操作:

    <li ng-repeat="for item in items" compact-list limit-to="3">{{item}}</li>
    

    指令的作用:

    • 给定的限制(在上面的示例中:3)应将显示的条目限制为最多3项
    • 将鼠标悬停在任何可见项上时,列表的其余部分也将显示(展开)
    • 在mouseout时,其他项目将再次隐藏-3个项目仍然可见

    因此,从用户的角度来看,关键是要有一个只读列表,它可能很长。为了不打乱我的布局,我希望将列表限制为几个条目。只有当用户悬停在压缩列表上时,它才会展开。哇,这是多么好的功能!

    从技术角度来看,这是我的基本概念:

    1. 指令 压缩列表 有一个 priority > 1000 ,因此在之前执行 ng-repeat 。它通过根据 $index 以及添加mouseover和mouseout事件
    2. 什么时候 ng重复 执行时,操作列表模板将为每个模板实例添加一个“隐藏项”CSS类 $index < limitTo
    3. 必须有一个全局开关( collapsed=false/true )
    4. 在mouseover上,指令全局开关 collapsed 通过例如。 ngClass 将显示隐藏的项目。这意味着,该列表已“扩展”
    5. 在mouseout上,指令全局开关 崩溃的 再次设置为真。通过 NG类 技巧,项目4…n将再次隐藏

    我设法完成了操作模板的工作。但我未能为“指令式全球切换”找到一个像样的解决方案。我可以使用什么角度机制将这样的变量附加到 压缩列表 指令,只有一个实例对所有对象有效 ng重复 项目?但是,它不能是“真正”全局的,因为同一页上可能有多个compactList指令。因此,只有全局到指令的“范围”。我在括号中写范围是因为 ng重复 创建 多个作用域 所以我不确定“父范围”到底在哪里。

    自从 ng重复 正在操作 <li> 乘以而不是 <ul> 标签,在我看来 压缩列表 在与ngRepeat相同的级别上,可能有一个级别太深。也许父元素必须配备这样的变量?但这听起来不太优雅。

    有人知道如何解决这个问题吗?注意:我绝对不是在寻找一些黑客解决方案。我想知道如何以优雅、角度一致的方式来实现这一点。我希望看到我的代码的人会惊叹而不是愤怒;)

    1 回复  |  直到 9 年前
        1
  •  0
  •   Community CDub    4 年前

    这有一个很好的解决方案 plunker :

    这是一个包含两个“列表”项的示例。

    <div ng-repeat="list in lists">
      <div ng-mouseleave="list.expand = false" ng-mouseover="list.expand = true" ng-repeat="item in list">
        <div ng-if="$first">
          List n° {{listIndex}}
        </div> 
        <div ng-show="$index < 3 || list.expand">
          {{item.value}}
        </div>
      </div>
     </div>
    

    我与 ng-mouseleave ng-mouseover 设置动态属性的 list.exand true false .

    值部分的显示取决于您想要的限制(可以在范围中的变量中定义)以及列表是否应该展开。

    ng-show="$index < 3 || list.expand"
    

    告诉我你是否认为这能满足你的需求。无论如何,您需要根据指令的工作方式对其进行调整。

    如果你想帮助我整合这一点,请分享你的指令代码(如果你在punker中放一个示例,那就更好了),我会尽我所能。

    希望有帮助

    编辑:

    我花了一些时间来实现这一指令,现在就是了。

    查看此中的用法 plunker

    我提出了两个应该这样使用的指令:

    <div ng-repeat="(listIndex,list) in lists">
       <div compact-list>
         <div ng-click="getClExpand()" ng-repeat="item in list">
          <div ng-if="$first">
            List n° {{listIndex}}
          </div> 
          <div limit-to="2">
            {{item.value}}
          </div>
        </div>
       </div>
     </div>
    

    这个 compact-list 指令添加 ng-mouseenter , ng鼠标离开 指令。

    这个 limit-to 添加 ng-show 根据你给的数字。

    压缩列表 指令

    app.directive('compactList', function ($compile) {
       return {
          restrict: 'A',
          controller:function($scope){
            $scope.clExpand = false;
          },
          replace: false,
          link: function link(scope,element, attrs) {
            //don't forget to remove the directive before the compile to avoid infinite digests.
            element.removeAttr("compact-list");
            element.attr("ng-mouseenter","clExpand = true");
            element.attr("ng-mouseleave","clExpand = false");
            $compile(element)(scope);
          }
        }; 
      });
    

    限制为 指令:

    app.directive('limitTo', function ($compile) {
        return {
          restrict: 'A',
          replace: false,
          //You can't use limit-to withouth compact-list
          require:"^^compactList",
          link: function link(scope,element, attrs) {
            element.attr("ng-show","$index < "+attrs.limitTo+" || clExpand");
            //don't forget to remove the directive before the compile to avoid infinite digests.
            element.removeAttr("limit-to");
            $compile(element)(scope);
          }
        };  
    });
    

    优点:您可以通过将限制设置为指令来选择要隐藏的项目部分。(如果要隐藏项目的描述,请将其放在description div中;如果要隐藏整个项目,请将它放在整个项目div中。)

    希望有帮助。

    编辑:

    (作者:andimeier)

    添加 scope=true 属性设置为 压缩列表 指令,它仍然更好(见我下面的评论)。所以 压缩列表 将是:

    压缩列表 指令

    app.directive('compactList', function ($compile) {
       return {
          restrict: 'A',
          scope: true,
          controller:function($scope){
            $scope.clExpand = false;
          },
          replace: false,
          link: function link(scope,element, attrs) {
            //don't forget to remove the directive before the compile to avoid infinite digests.
            element.removeAttr("compact-list");
            element.attr("ng-mouseenter","clExpand = true");
            element.attr("ng-mouseleave","clExpand = false");
            $compile(element)(scope);
          }
        }; 
      });