AngularJS - 如何在没有HTML元素的情况下使用ng-if

61

有没有一种方法告诉AngularJS不要显示具有ng-if指令的顶部HTML元素。我只想让angular显示子内容。

Angular 代码:

有没有办法告诉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>

这里有一个 JSFiddle 示例:http://jsfiddle.net/9mgTS/。我不想在HTML中使用 #div1,只想在checkedtrue时使用#div2,3,4

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


1
没有办法告诉Angular不输出父元素,除非创建一个带有自定义模板的指令。您可以使用template:function(el,attrs)根据属性运行一些逻辑并返回适当的HTML。 - charlietfl
请查看以下两个网址:https://dev59.com/Mmcs5IYBdhLWcg3wHwRH 和 https://dev59.com/o2Ag5IYBdhLWcg3w7erx。 - Umidbek
2
在Angular2中(如果有人不小心到达这里),请使用ng-container:<ng-container *ngIf="true"> - Alexander Taylor
6个回答

58

可以使用目前没有文档的一对指令ng-if-startng-if-end来实现这一点。它们的行为类似于ng-repeat-startng-repeat-end指令,如果需要,您可以查看它们的单元测试

例如,给定以下代码:

<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>

将显示前四个 li,并隐藏最后四个 li

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

还有 ng-show-startng-show-end 指令,它们的作用方式与您所期望的完全相同。


7
如果您愿意创建一个自定义指令,可以通过编程方式将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();
                }
            }
        }
    }
})

Angular 代码:

<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>

Fiddle: http://jsfiddle.net/o166xg0s/4/


0
这是一个关于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


-1

这似乎是一个老问题,但我有类似的需求。

<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元素并且不会影响布局,这对我有效。


有人能解释一下为什么这个被踩了吗?是的,它应该被踩。但是没有人说原因。 - TamusJRoyce

-1

我不明白为什么你不想使用父级 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'}
    }
});

:( . 哎呀,这个解决方案把视图和控制器混在一起了。我想要保持它们分开。 - waqas
2
一个很好的理由是,如果你想隐藏或显示一组子元素,但不想在这些子元素周围添加另一个标签。 - sinθ

-2

试一下:- 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>

编辑:

使用AngularJS和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>

1
谢谢您的回复,但这不是我要找的。我不想在所有子元素中添加ng-if。想象一下维护20多个子元素与ng-if的关系。如果有人必须将“checked”更改为“checked2”,那么必须在20多个地方进行更改。您有其他建议吗? - waqas
@waqas - 然后在具有ng-if的div上方使用父div <div ng-if="checked"> - Aditya Singh
@waqas 或者你可以在所有的div上方创建一个任意标签<mylist>。http://jsfiddle.net/adiioo7/9mgTS/2/ - Aditya Singh
IE不支持自定义标签。此外,添加<mylist>并不能解决问题。我们仍然有一个包含ng-if的父标签。我们想要摆脱包含ng-if的父标签。 - waqas
@waqas 请查看 EDIT - Aditya Singh
6
我认为@waqas正在寻找类似于良好的模板引擎中所看到的东西,例如{{ if (condition) }} <my html...> {{ end if }}。遗憾的是Angular似乎无法做到这一点。Angular似乎强制用户在纯逻辑场景下使用HTML元素,这相当愚蠢。 - Joshua

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接