角度 - 我可以在嵌套的 ng-repeat 中的多个对象上使用单个函数来触发该对象的 ng-show 吗?

Angular - can I use a single function on multiple objects within a nested ng-repeat that triggers the ng-show of just that object?

本文关键字:对象 函数 单个 ng-show 嵌套 我可以 ng-repeat 角度      更新时间:2023-09-26

SUMMARY
我有一个品牌列表和一个产品列表。我正在使用 ng-repeat 来显示品牌列表,并使用带有过滤器的 ng-repeat 来显示各自品牌中的产品列表。我希望每个品牌和每个产品都有一个按钮,可以显示有关该品牌/产品的更多信息。所有这些按钮都应在控制器上使用相同的功能。

PROBLEM
显示有关该品牌的更多信息的按钮也显示了有关该品牌每个产品的更多信息,除非(这对我来说很奇怪(我首先单击该品牌内产品的按钮,在这种情况下它将正常工作。

CODE
请在此处查看 Plunker,请注意,当您单击品牌上的"显示类型"时,它还会显示该品牌内所有类型的产品:http://plnkr.co/edit/gFnq3O3f0YYmBAB6dcwe?p=preview

.HTML

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="style.css">
    <script src="script.js"></script>
  </head>
  <body>
    <div ng-app="myApp">
      <div ng-controller="MyController as vm">
        <div ng-repeat="brand in brands">
          <h1>
              {{brand.name}}
            </h1>
          <button ng-click="showType(brand)">
            Show Brand Type
          </button>
          <div ng-show="show">
            {{brand.type}}
          </div>
          <div ng-repeat="product in products
          | filter:filterProducts(brand.name)">
            <h2>
                  {{product.name}}
                </h2>
            <button ng-click="showType(product)">
              Show Product Type
            </button>
            <div ng-show="show">
              {{product.type}}
            </div>
          </div>
        </div>
      </div>
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
    <script src="script.js"></script>
  </body>
</html>

JAVASCRIPT

var app = angular.module('myApp', []);
app.controller('MyController', function($scope) {
  $scope.brands = [{
    name: 'Kewl',
    type: 'Cereal'
  }, {
    name: 'Joku',
    type: 'Toy'
  }, {
    name: 'Loko',
    type: 'Couch'
  }]
  $scope.products = [{
    name: 'Kewlio',
    type: 'Sugar Cereal',
    brand: 'Kewl'
  }, {
    name: 'Kewliano',
    type: 'Healthy Cereal',
    brand: 'Kewl'
  }, {
    name: 'Jokurino',
    type: 'Rattle',
    brand: 'Joku'
  }, {
    name: 'Lokonoko',
    type: 'Recliner',
    brand: 'Loko'
  }, {
    name: 'Lokoboko',
    type: 'Love Seat',
    brand: 'Loko'
  }]
  $scope.showType = function(item) {
    this.show = !this.show;
  }
  $scope.filterProducts = function(brand) {
    return function(value) {
      if(brand) {
        return value.brand === brand;
      } else {
        return true;
      }
    }
  }
});

重要说明:我意识到我可以向对象添加一个属性 (brand.show( 并将对象传递到函数中,然后将该属性更改为 true/false,但我不想这样做,因为在我的实际应用程序中,该按钮将显示一个编辑品牌/产品并将信息提交给 Firebase 的表单, 而且我不希望对象上有"show"属性。我宁愿不必在每次我想编辑Firebase.
中的信息时都删除"show"属性

当你

这样做时,ng-repeat指令创建自己的作用域

this.show = !this.show

当前范围内创建/更改show属性,如果单击"品牌"按钮 - 对于"品牌范围",则单击"全局"用于">产品"按钮 - 对于"范围具体产品"。

为避免这种情况,您应该在单击按钮之前创建此属性,例如使用 ng-init ,例如

ng-init="show=false;"

在带有"ng-repeat"指令的元素上

样本

var app = angular.module('myApp', []);
app.controller('MyController', function($scope) {
  $scope.brands = [{
    name: 'Kewl',
    type: 'Cereal'
  }, {
    name: 'Joku',
    type: 'Toy'
  }, {
    name: 'Loko',
    type: 'Couch'
  }]
  $scope.products = [{
    name: 'Kewlio',
    type: 'Sugar Cereal',
    brand: 'Kewl'
  }, {
    name: 'Kewliano',
    type: 'Healthy Cereal',
    brand: 'Kewl'
  }, {
    name: 'Jokurino',
    type: 'Rattle',
    brand: 'Joku'
  }, {
    name: 'Lokonoko',
    type: 'Recliner',
    brand: 'Loko'
  }, {
    name: 'Lokoboko',
    type: 'Love Seat',
    brand: 'Loko'
  }]
  $scope.showType = function(item) {
    this.show = !this.show;
  }
  $scope.filterProducts = function(brand) {
    return function(value) {
      if (brand) {
        return value.brand === brand;
      } else {
        return true;
      }
    }
  }
});
/* Styles go here */
h1 {
  font-family: impact;
}
h2 {
  font-family: arial;
  color: blue;
  margin-bottom: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<div ng-app="myApp">
  <div ng-controller="MyController as vm">
    <div ng-repeat="brand in brands" ng-init="show=false">
      <h1>
              {{brand.name}}
            </h1>
      <button ng-click="showType(brand)">
        Show Brand Type
      </button>
      <div ng-show="show">
        {{brand.type}}
      </div>
      <div ng-repeat="product in products
          | filter:filterProducts(brand.name)" ng-init="show=false">
        <h2>
           {{product.name}}
        </h2>
        <button ng-click="showType(product)">
          Show Product Type
        </button>
        <div ng-show="show">
          {{product.type}}
        </div>
      </div>
    </div>
  </div>
</div>

如果您不介意在数据中放置临时属性,最简单的解决方法是以下更改:

<div ng-show="product.show">
   {{product.type}}
</div>

<div ng-show="brand.show">
   {{brand.type}}
</div>

然后在控制器中

$scope.showType = function(item) {
    item.show = !item.show;
  }

或者,如果您不想触摸对象属性,则可以创建一个 $scope.displayTypes 数组,然后单击将对象推入显示的数组或从中显示的数组中删除对象。 您可以检查对象在数组中是否存在,并适当地显示或不显示类型。 如果您需要样本,请告诉我。

您的show布尔属性对于整个树相同(在相同的范围内(。将角度指令与ng-repeat中的子作用域scope:true一起使用有助于隔离每个show属性。我已经分叉了你的 plunker 代码:

http://plnkr.co/edit/cMSvyfeCQOnTKG8F4l55?p=preview