使用AngularJS的ng-repeat选择第二个孩子



我在Symfony2应用程序中使用了一个捆绑包,它在标记中使用了Angular:

...some table structure
<th ng-repeat="column in columns" ng-show="column.visible">
    <input ng-if="column.filter != false" ng-model="params.filter()[column.index]" type="text" name="{{ column.index }}" value="" class="form-control input-sm" />
</th>

我不允许更改这个捆绑包的代码,但我需要选择这个ng重复的第二个thinput(我使用jQuery)。它在输入元素中的名称是name="_domain"。我设法选择了所有的输入:

$('#translation-grid table thead tr th input')

但这两者都不是:

$('#translation-grid table thead tr th input[name=_domain]')

或者这个:

$('#translation-grid table thead tr th:nth-child(2) input')

正在工作。我只找到了需要更改角度标记的解决方案,但我做不到。我只需要选择这个input

jquery选择器没有任何问题。我在评论中的意思是,它可能执行得太早(在ng-repeat/ng-if/and-what-else-you-are-using-on-the-page完成之前)。

打开页面,打开控制台,然后键入类似$('#translation-grid table thead tr th input').css('background-color', 'yellow')的内容。如果这样做有效,那么几乎可以肯定的是,执行选择器的时间太快了。另一种简单的检查方法是在选择器之前插入一个简单的alert。这将阻止当前的摘要,如果此时该表未在DOM中呈现,则jquery也无法定位它。

如果在指令中执行此操作,则可能需要尝试将其移动到postlink函数,或将priority设置为负值。否则,请尝试将其包装到一个不带延迟集的$timeout调用中,该调用将对您的语句进行排队,直到当前摘要周期结束。

$timeout(function() {
    $('#translation-grid table thead tr th input')
      .css('background-color', 'yellow');
});

示例

下面的示例试图突出显示4列。

  1. 直接在控制器中:不起作用
  2. 带有排队$timeout:有效
  3. 直接从指令:不起作用
  4. 通过点击按钮从用户界面:工作

Plunker可以在这里找到。

// Code goes here
function highlite(index, color) {
  alert('Trying to highlite column ' + index + ' with color ' + color);
  $('.table th:nth-child(' + index + ')').css('background-color', color);
}
var app = angular.module('app', []);
app.controller('MyController', function($scope) {
  $scope.columns = [
    'First Name', 'Last Name', 'Username', 'Age', 'Sex'
  ];
  $scope.rows = [
    ['Mark', 'Otto', '@mdo', 10, true],
    ['Jacob', 'Thornton', '@fat', 20, false],
    ['Larry', 'the Bird', '@twitter', 30, true]
  ];
  // Expose highlite function to view 
  $scope.highlite = highlite;
  // This does not work; both the directive template and the ng-repeat
  // hasn't been executed yet.
  highlite(1, 'purple');
});
app.directive('myTable', function($timeout) {
  return {
    restrict: 'AE',
    template: '<table class="table">' +
                '<thead>' +
                  '<tr>' +
                    '<th ng-repeat="column in columns">{{ column }}</th>' +
                  '</tr>' +
                '</thead>' +
                '<tbody>' +
                  '<tr ng-repeat="row in rows">' +
                    '<td ng-repeat="field in row">' +
                      '{{ field }}' +
                    '</td>' +
                  '</tr>' +
                '</tbody>' +
              '</table>',
    scope: {
      columns: '=',
      rows: '='
    },
    link: function($scope, $element) {
      // This won't work either; the ng-repeat hasn't fired yet
      highlite(3, 'blue');
      // ... but this will: queue the provided function to execute when
      // the current digest cycle has been finished (after the ng-repeat).
      $timeout(function() {
        highlite(4, 'orange');
      });
    }
  };
});
<link rel="stylesheet" 
      href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<script src="https://code.angularjs.org/1.4.0-beta.6/angular.js"></script>
<script src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
<div ng-app="app" ng-controller="MyController" class="container">
  <h1>Hello Plunker!</h1>
  <my-table columns="columns" 
            rows="rows">
  </my-table>
  <!-- 
    This will work because the select statement is 
    executed after the ng-repeat has finisched 
  -->
  
  <button class="btn btn-primary" 
          ng-click="highlite(2, 'yellow')">
    Click me!
  </button>
</div>

为什么不$('#translation-grid table thead tr th input')[1]?由于您可以选择所有元素,因此也可以在阵列中拾取一个。

要使用$index,需要通过包含自定义数据属性(如data-index="{{$index}}")来修改角度。这会将数据索引属性分配给值等于ng重复循环中索引的元素,因此可以在jquery中使用表达式$('#translation-grid table thead tr th input[data-index=1]')引用该属性。