【问题标题】:AngularJS - How to use ng-if without HTML elementAngularJS - 如何在没有 HTML 元素的情况下使用 ng-if
【发布时间】:2013-11-01 05:38:14
【问题描述】:

有没有办法告诉 AngularJS 不要显示具有 ng-if 指令的顶部 HTML 元素。我希望 Angular 仅显示子内容。

角度代码:

    <div ng-if="checked" id="div1">
      <div id="div2">ABC</div>
      <div id="div3">KLM</div>
      <div id="div4">PQR</div>
   </div>

呈现的 HTML:

   <div id="div1"> 
      <div id="div2">ABC</div>
      <div id="div3">KLM</div>
      <div id="div4">PQR</div>
   </div>

我想要什么:

   <div id="div2">ABC</div>
   <div id="div3">KLM</div>
   <div id="div4">PQR</div>

这是一个小提琴。 http://jsfiddle.net/9mgTS/。我不想在 HTML 中使用 #div1。如果checkedtrue,我只想要#div2,3,4

一种可能的解决方案是向所有子元素添加 ng-if,但我不想这样做。

【问题讨论】:

标签: javascript angularjs angularjs-ng-if


【解决方案1】:

您可以使用一对当前未记录的指令ng-if-startng-if-end。它们的行为类似于记录在案的 ng-repeat-start and ng-repeat-end 指令,如果您愿意,可以查看 unit tests for them

例如,给定以下代码:

<ul>
  <li ng-if-start="true">a</li>
  <li>b</li>
  <li>c</li>
  <li ng-if-end>d</li>
  <li ng-if-start="false">1</li>
  <li>2</li>
  <li>3</li>
  <li ng-if-end>4</li>
</ul>

前四个lis 将被显示,最后四个lis 将被隐藏。

这是 CodePen 上的一个实时示例:http://codepen.io/anon/pen/PqEJYV

还有 ng-show-startng-show-end 指令完全按照您的预期工作。

【讨论】:

    【解决方案2】:

    如果您乐于创建自定义指令,您可以通过编程方式将 ng-if 应用于子级,并在此过程中展平 DOM:

    指令代码:

    .directive('ngBatchIf', function() {
        return {
            scope: {},
            compile: function (elm, attrs) {
                // After flattening, Angular will still have the first element
                // bound to the old scope, so we create a temporary marker 
                // to store it
                elm.prepend('<div style="display: none"></div>');
    
                // Flatten (unwrap) the parent
                var children = elm.children();
                elm.replaceWith(children);
    
                // Add the ng-if to the children
                children.attr('ng-if', attrs.ngBatchIf);
    
                return {
                    post: function postLink(scope, elm) {
                        // Now remove the temporary marker
                        elm.remove();
                    }
                }
            }
        }
    })
    

    角度代码:

    <div id="div1" ng-batch-if="checked">
        <div id="div2">ABC</div>
        <div id="div3">KLM</div>
        <div id="div4">PQR</div>
    </div>
    

    呈现的 HTML:

    <div id="div2" ng-if="checked">ABC</div>
    <div id="div3" ng-if="checked">KLM</div>
    <div id="div4" ng-if="checked">PQR</div>
    

    小提琴:http://jsfiddle.net/o166xg0s/4/

    【讨论】:

      【解决方案3】:

      这是一个 Angular 1.21 解决方案:

      HTML:

      <div ng-app="app" ng-controller="ctrl">
          <div ng-iff="checked" id="div1">
              <div id="div2">ABC</div>
              <div id="div3">KLM</div>
              <div id="div4">PQR</div>
          </div>
          <button ng-click="toggleCheck()">Toggle Check</button>
      </div>
      

      JAVASCRIPT:

      angular.module('app', []).
      controller('ctrl', function ($scope) {
          $scope.checked = true;
      
          $scope.toggleCheck = function () {
              $scope.checked = !$scope.checked;
          };
      }).
      directive('ngIff', function ($compile) {
          return {
              compile: function compile(tElement, tAttrs, transclude) {
                  return {
                      pre: function preLink(scope, iElement, iAttrs, controller) {
                          var bindingElem = iElement.attr('ng-iff');
                          var children = iElement.children();
      
                          angular.forEach(children,function(c){
                              angular.element(c).attr('ng-if',bindingElem);
                          });
      
                          $compile(children)(scope, function(newElem){
                              iElement.replaceWith(newElem);
                          });
                      }
                  };
              }
          };
      });
      

      JSFIDDLE.

      【讨论】:

        【解决方案4】:

        我不明白你为什么不想使用父 div,但如果你有 +20 个 div,这将是一个很好的解决方案:

        HTML

           <div ng-repeat="div in divs" ng-if="checked" id="{{div.name}}">{{div.content}}</div>
        

        JS

        app.controller('myCtrl', function($scope) {
            $scope.checked = true;
            $scope.divs = {
                 {'name': 'div2', content:'ABC'},
                 {'name': 'div3', content:'KLM'},
                 {'name': 'div4', content:'PQR'}
            }
        });
        

        【讨论】:

        • :( . Nah.. 这个解决方案是将视图与控制器混合在一起。我想将它们分开。
        • 一个很好的理由是,如果您想隐藏或显示一组孩子,但又不想在这些孩子周围添加另一个标签。
        【解决方案5】:

        似乎是一个老问题,但我有类似的要求

        <div ng-if="checked" id="div1">
              <div id="div2">ABC</div>
              <div id="div3">KLM</div>
              <div id="div4">PQR</div>
        </div>
        

        我是这样管理的

        <mytag ng-if="checked" id="div1">
              <div id="div2">ABC</div>
              <div id="div3">KLM</div>
              <div id="div4">PQR</div>
        </mytag>
        

        其中 mytag 是任何不是 html 元素的名称,只要它不干扰布局,这对我有用

        【讨论】:

        • 有人能解释一下为什么这被否决了吗?是的。它应该被否决。但没有人说出原因。
        【解决方案6】:

        试试这个:- http://jsfiddle.net/adiioo7/9mgTS/1/

        div1div2,div3,div4 的父容器,如果您不想在输出 html 中使用 div1,请使用:-

        <div ng-app="App">Click me:
            <input type="checkbox" ng-model="checked" ng-init="checked=true" />
            <br/>Show when checked:
            <div class="div2" ng-if="checked">ABC</div>
            <div class="div3" ng-if="checked">KLM</div>
            <div class="div4" ng-if="checked">PQR</div>
        </div>
        

        编辑:-

        使用 Angular js 和 jQuery:-http://jsfiddle.net/adiioo7/9mgTS/3/

        为属于该组的所有元素分配一个公共类(例如myClass)。

        JS:-

        angular.module('App', []);
        
        function myController($scope) {
            $scope.change = function () {
                angular.element(".myClass").toggle();
            };
        }
        

        HTML:-

        <div ng-app="App" ng-Controller="myController">Click me:
            <input type="checkbox" ng-change="change()" ng-model="checked" ng-init="checked=true" />
            <br/>Show when checked:
            <div id="div2" class="myClass">ABC</div>
            <div id="div3" class="myClass">KLM</div>
            <div id="div4" class="myClass">PQR</div>
        </div>
        

        【讨论】:

        • 感谢您的回复,但这不是我想要的。我不想将 ng-if 添加到所有子元素。想象一下使用 ng-if 维护 20 多个子元素。如果有人必须将“checked”更改为“checked2”,则必须在 20 多个地方进行。您还有什么建议吗?
        • @waqas - 然后在 div 的顶部使用父 div 和 ng-if &lt;div ng-if="checked"&gt;
        • @waqas 或者您可以在所有 div jsfiddle.net/adiioo7/9mgTS/2 之上创建一个任意标签 &lt;mylist&gt;
        • IE 不支持自定义标签。此外,添加 并不能解决问题。我们还有一个父标签。我们想去掉包含 ng-if 的父标签。
        • 我相信@waqas 正在寻找更像您在体面的模板引擎中看到的东西,例如 {{ if (condition) }} {{ end if }}。遗憾的是 Angular 似乎无法做到这一点。 Angular 似乎强迫用户在纯逻辑场景中使用 HTML 元素——这非常愚蠢。
        猜你喜欢
        • 2012-07-14
        • 2015-11-28
        • 2020-07-10
        • 2012-10-03
        • 1970-01-01
        • 1970-01-01
        • 2015-09-16
        • 1970-01-01
        • 2014-09-24
        相关资源
        最近更新 更多