2014-04-29 177 views
2

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

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

选项卡可能实现为具有隔离范围并且不与其他范围构成父/子关系的指令。除此之外,似乎你已经分享了很多代码,但我不确定是什么问题。 – JeffryHouser

+0

你是对的Tabs是一个指令。我在这些下拉菜单中需要调用父范围的函数。我相信这个范围是被横扫的。 –

回答

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

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

新的NG-重复

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

为什么你使用下划线的foreach这只是一个synomym的JavaScript foreach?你正在写一个角度应用程序,并在角度上下文中,你不应该使用angular.foreach吗? – mortsahl

+0

嘿mortashi,说实话?习惯。我对下划线感到非常舒服,所以我在各地都使用它。对于这个项目我不需要支持IE8,所以我可以使用JavaScript的每一个,但在现实世界中使用这个特定的应用程序,我没有注意到性能差异。感谢大家的支持,我不应该懒惰地按照习惯编写代码。 –

2

范围是有趣和令人困惑。除$ rootScape外,所有范围都有祖先。我不确定,但我认为ui-bootstrap tabset创建了自己的隔离范围。这个隔离范围确实有一个父级,但是你已经“隔离”它,所以它不能看到祖先范围的任何属性,除非你已经明确地将它们包含在指令中。如果隔离范围具有不是孤立范围的子范围,则它可以查看和操纵其父项属性,但不会远离祖先链。事件可以自由地上下传递,你应该非常小心地使用它们,因为在处理隔离范围时,可能会导致你不期望的副作用。

如果上面只是一堆乱七八糟的东西,请到https://docs.angularjs.org/guide/directive并重新阅读那里的信息 - 也许这会让它更加清晰。

这里大概范围上最好的论文,你会在一个快速,简洁和清晰的解释测量值的一个 - What are the nuances of scope prototypal/prototypical inheritance in AngularJS?