Select 第二 child 和 AngularJS 的 ng-repeat

Select second child with AngularJS's 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>

我不能更改这个包的代码,但我需要 select input 这个 ng-repeat 的第二个 th (我使用 jQuery).它在输入元素中的名称是 name="_domain"。我设法 select 所有输入:

$('#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')

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

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

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

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 。这将阻止当前的 digest,如果 table 没有在 DOM 中呈现,那么 jquery 也找不到它。

如果您在指令中执行此操作,您可能想尝试将其移动到 post link 函数或设置 priority 负数 值。否则尝试将其包装到一个没有延迟设置的 $timeout 调用中,这将使您的语句排队直到当前 digest 周期结束。

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

例子

下面的示例尝试对 4 列进行高亮显示。

  1. 直接在控制器中:不起作用
  2. 排队 $timeout:有效
  3. 直接来自指令:不起作用
  4. 从 UI 中按一下按钮:有效

可以找到 Plunker here

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