ui-bootstrap选项卡的范围问题

时间:2014-04-29 20:06:08

标签: angularjs angular-ui-bootstrap

我在理解范围方面遇到了问题。当你使用tabset时,ui-bootstrap会创建一个新的范围,我明白了。我认为父方法可用于子范围?这是一个显示我的问题的jsbin。

JSBin

我确定有一些简单的东西我没有丢失,但是我无法看到它。

代码内联以防JSBin起作用:

angular.module('app', ['ui.bootstrap'])
.controller('MainController', function($scope) {
  $scope.filters = [];
  $scope.search = '';
  $scope.providerVersions = [
    { name:'SomeOS', type:'pv' },
    { name:'OtherOS', type:'pv' }
  ];
  $scope.scripts = [
    { name:'Something', pv:'SomeOS', type:'script' },
    { name:'Somebody', pv:'SomeOS', type:'script' },
    { name:'Other thing', pv:'OtherOS', type:'script' },
    { name:'Other body', pv:'OtherOS', type:'script' }
  ];

  $scope.addFilter = function(f) {
    $scope.filters.push({ name:f.name, type:f.type });
  };

  $scope.remFilter = function(i) {
    $scope.filters.splice(i,1);
  };

  $scope.filterByName = function(n) {
      var name = n.name.toLowerCase();
      var search = $scope.search.toLowerCase();
      return name.indexOf(search) > -1;
  };

  $scope.filterByFilters = function(f) {
    if ($scope.filters.length===0) { return true; }

    var byName = _.where($scope.filters, { type:'script' });
    if (byName.length > 0) {
      return _.contains(_.pluck(byName, 'name'), f.name);
    }
    return _.contains(_.pluck($scope.filters, 'name'), f.pv);
  };
});

HTML

<body ng-app="app">
  <div ng-controller="MainController">
    <h3>This works</h3>
    <p>Filters on both name and role as expected.</p>
    <div ng-repeat="s in scripts|filter:filterByFilters">
      {{ s.name }}
    </div>
    <form name="searchForm">
      <input type="text" class="form-control" placeholder="Filter by name or role" ng-model="search">
    </form>
    <span ng-repeat="f in filters"><a ng-click="remFilter($index)">{{ f.name }}</a><span ng-if="!$last">, </span></span>
    <ul ng-show="search.length>0" class="dropdown-menu" style="display:block; position:static;">
      <li class="dropdown-header">Name</li>
      <li ng-repeat="s in scripts|filter:filterByName"><a  ng-click="addFilter(s)">{{ s.name }}</a></li>
  <li class="divider"></li>
      <li class="dropdown-header">Role</li>
      <li ng-repeat="p in providerVersions|filter:search"><a ng-click="addFilter(p)">{{ p.name }}</a></li>
</ul>

    <h3>This does not work</h3>
    <p>Only filters on role. It does not call $scope.filterByName.</p>
    <tabset>
      <tab heading="Scripts">
        <div ng-repeat="s in scripts|filter:filterByFilters">
      {{ s.name }}
    </div>
    <form name="searchForm">
      <input type="text" class="form-control" placeholder="Filter by name or role" ng-model="search">
    </form>
    <span ng-repeat="f in filters"><a ng-click="remFilter($index)">{{ f.name }}</a><span ng-if="!$last">, </span></span>
    <ul ng-show="search.length>0" class="dropdown-menu" style="display:block; position:static;">
      <li class="dropdown-header">Name</li>
      <li ng-repeat="s in scripts|filter:filterByName"><a  ng-click="addFilter(s)">{{ s.name }}</a></li>
  <li class="divider"></li>
      <li class="dropdown-header">Role</li>
      <li ng-repeat="p in providerVersions|filter:search"><a ng-click="addFilter(p)">{{ p.name }}</a></li>
</ul>
      </tab>
    </tabset>
  </div>
</body>

2 个答案:

答案 0 :(得分:2)

范围很有趣且令人困惑。除$ rootScape之外的所有范围都有祖先。我不确定,但我认为ui-bootstrap tabset创建了自己的隔离范围。隔离范围确实有父母,但你已经隔离了&#34;因此它无法看到祖先范围的任何属性,除非您在指令中明确包含它们。如果隔离范围的子范围不是隔离范围,它可以查看和操纵其父项属性,但不能追溯到祖先链的后面。事件可以自由地在链中上下传递,你应该非常小心地使用它们,因为在处理隔离范围时,可能会引起你不期望的副作用。

如果以上只是一堆喋喋不休,请转到https://docs.angularjs.org/guide/directive并重读那里的信息 - 也许这会让它更清晰。

这里可能是关于范围的最佳论文之一,您将以快速,简洁和清晰的解释 - What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

答案 1 :(得分:0)

我能够解决这个问题。老实说,我不知道为什么会这样,但确实如此。也许其他人可以为我填补空白。我所做的不是尝试过滤我的列表,而是更改了过滤器函数以返回一个数组,并使用该结果进行ng-repeat迭代。

旧过滤功能

$scope.filterByName = function(n) {
  var name = n.name.toLowerCase();
  var search = $scope.search.toLowerCase();
  return name.indexOf(search) > -1;
};

新过滤功能

$scope.filterByName = function(list, srch) {
        var ret = [];

        _.each(list, function(l) {
            if (l.name.toLowerCase().indexOf(srch.toLowerCase()) > -1) {
                ret.push(l);
            }
        });

        return ret;
    };

旧ng-repeat

<li ng-repeat="s in scripts|filter:filterByName">

新ng-repeat

<li ng-repeat="s in filterByName(scripts, search)">