【问题标题】:AngularJS sorting not workingAngularJS排序不起作用
【发布时间】:2016-06-29 19:16:17
【问题描述】:

我有两张桌子。 一种有效,一种无效。

我的目标是: 我想修复不工作的表。

它们之间的唯一区别是工作表中的表头 值是硬编码的。

下面是代码:

 <!-- Not working table -->

<table style="margin-left:100px">
    <thead>
        <tr>
            <th style="width:100px;font-weight:bold;cursor:pointer" 
            ng-repeat="value in field_names" ng-click="orderByField='{{value}}'; reverseSort = !reverseSort">
            {{value}}  <span ng-show="orderByField == '{{value}}'">
            <span ng-show="!reverseSort">^</span>
            <span ng-show="reverseSort">v</span>
                    </span>
            </th>
        </tr>           
    </thead>

    <tbody>

    <tr ng-repeat="emp in dataArray|orderBy:orderByField:reverseSort">
        <td>{{emp.a}}</td>
        <td>{{emp.b}}</td>
        <td>{{emp.c}}</td>
    </tr>

    </tbody>

</table>

<!-- working table -->


<table class="table table-bordered">
<thead>
  <tr>
    <th ng-click="orderByField='firstName'; reverseSort = !reverseSort">
      First Name <span ng-show="orderByField == 'firstName'">
      <span ng-show="!reverseSort">^</span>
      <span ng-show="reverseSort">v</span></span>
    </th>
    <th ng-click="orderByField='lastName'; reverseSort = !reverseSort">
        Last Name <span ng-show="orderByField == 'lastName'"><span ng-show="!reverseSort">^</span><span ng-show="reverseSort">v</span></span>
    </th>
    <th ng-click="orderByField='age'; reverseSort = !reverseSort">
      Age <span ng-show="orderByField == 'age'"><span ng-show="!reverseSort">^</span><span ng-show="reverseSort">v</span></span>
    </th>
  </tr>
</thead>
<tbody>
  <tr ng-repeat="emp in data.employees|orderBy:orderByField:reverseSort">
    <td>{{emp.firstName}}</td>
    <td>{{emp.lastName}}</td>
    <td>{{emp.age}}</td>
  </tr>
</tbody>

而 javascript 是:

$scope.field_names= [];
$scope.table_data={};

$scope.orderByField;

   $scope.dataArray = [{
        a: "Hans",
        b: "Mueller",
        c: "Leipzig"
    }, {
        a: "Dieter",
        b: "Zumpe",
        c: "Berlin"
    }, {
        a: "Bernd",
        b: "Danau",
        c: "Muenchen"

}];

 $scope.data = {
employees: [{
  firstName: 'John',
  lastName: 'Doe',
  age: 30
},{
  firstName: 'Frank',
  lastName: 'Burns',
  age: 54
},{
  firstName: 'Sue',
  lastName: 'Banter',
  age: 21
}]


};

   $scope.reverseSort = false;
function getHeaders(){
    $scope.field_names=Object.keys($scope.dataArray[0]);
    }


getHeaders();

【问题讨论】:

标签: angularjs angularjs-directive angularjs-scope


【解决方案1】:

您遇到了 ng-repeatorderByField 的范围界定问题。 这是为什么现在 angularJS 团队推荐使用“controller as”语法的一个典型例子。 Here is a great article to explain

另请注意 - 您不需要 ng-click="orderByField = value"ng-show="orderByField === value" 中的花括号

这与您当前的代码有何关系:

您需要使用 ng-controller="ctrl as name" 将所有内容放在同一范围内,这样您的ng-repeat 创建的每个&lt;th&gt; 都不会创建自己的orderByField 实例。代码如下所示:

WORKING DEMO

HTML

<body ng-app="myApp" ng-controller="myCtrl as Main">
 <!-- Not working table -->
<table style="margin-left:100px">
    <thead>
        <tr>
            <th style="width:100px;font-weight:bold;cursor:pointer" 
                ng-repeat="value in Main.field_names" 
                ng-click="Main.orderByField = value; Main.reverseSort = !Main.reverseSort">
            {{value}}  <span ng-show="Main.orderByField == value">
            <span ng-show="!Main.reverseSort">^</span>
            <span ng-show="Main.reverseSort">v</span>
                    </span>
            </th>
        </tr>           
    </thead>

    <tbody>

    <tr ng-repeat="emp in Main.dataArray|orderBy:Main.orderByField:Main.reverseSort">
        <td>{{emp.a}}</td>
        <td>{{emp.b}}</td>
        <td>{{emp.c}}</td>
    </tr>

    </tbody>

</table>

<!-- working table -->


<table class="table table-bordered">
<thead>
  <tr>
    <th ng-click="Main.orderByField='firstName'; Main.reverseSort = !Main.reverseSort">
      First Name <span ng-show="Main.orderByField == 'firstName'">
      <span ng-show="!Main.reverseSort">^</span>
      <span ng-show="Main.reverseSort">v</span></span>
    </th>
    <th ng-click="Main.orderByField='lastName'; Main.reverseSort = !Main.reverseSort">
        Last Name <span ng-show="Main.orderByField == 'lastName'"><span ng-show="!Main.reverseSort">^</span><span ng-show="Main.reverseSort">v</span></span>
    </th>
    <th ng-click="Main.orderByField='age'; Main.reverseSort = !Main.reverseSort">
      Age <span ng-show="Main.orderByField == 'age'"><span ng-show="!Main.reverseSort">^</span><span ng-show="Main.reverseSort">v</span></span>
    </th>
  </tr>
</thead>
<tbody>
  <tr ng-repeat="emp in Main.data.employees|orderBy:Main.orderByField:Main.reverseSort">
    <td>{{emp.firstName}}</td>
    <td>{{emp.lastName}}</td>
    <td>{{emp.age}}</td>
  </tr>
</tbody>
</body>

Javascript

var app = angular.module("myApp", [])
.controller("myCtrl", function ($scope) {
  var $this = this;
  $this.field_names= [];
  $this.table_data={};

  $this.orderByField = "";

  $this.dataArray = [
     {
        a: "Hans",
        b: "Mueller",
        c: "Leipzig"
     }, 
     {
        a: "Dieter",
        b: "Zumpe",
        c: "Berlin"
     }, 
     {
        a: "Bernd",
        b: "Danau",
        c: "Muenchen"
     }
];

$this.data = {
employees: [{
  firstName: 'John',
  lastName: 'Doe',
  age: 30
},{
  firstName: 'Frank',
  lastName: 'Burns',
  age: 54
},{
  firstName: 'Sue',
  lastName: 'Banter',
  age: 21
}]


};

$this.reverseSort = false;
function getHeaders(){
  $this.field_names=Object.keys($this.dataArray[0]);
}


getHeaders();
});

【讨论】:

  • 好吧,由于某种原因,这是可行的......但是这里有三件事我不明白......为什么你使用 var $this = this 将所有内容更改为全局......其次,如果您想更改为全局,您不能这样做:this.orderByField 而不是 $this.orderByField .....最后变量“Main”来自哪里?由于 y,正在使用 Main.orderByField 和 Main.reverseSort....等
  • @Simon 如果您阅读了我链接的文章,您将了解它是如何/为什么起作用的,以及“Main”的来源。至于使用“var $this = this”,这是我使用的约定,因为“this”根据范围不明确。一旦您输入任何迭代函数(foreach、map、filter 等)、ajax 回调和许多其他函数,“this”将成为本地函数的范围,并且您将失去对顶级“this”的引用,除非您保存它变成一个变量。使用 "$this = this" 可以为您提供对顶级 "this" 的一致明确和明确的引用。
【解决方案2】:

您不需要在 ng-clickng-show 指令中使用大括号 {{}}。

它的内容将被评估,value 变量已经包含一个字符串。

所以只需使用像

这样的表达式
ng-click="orderByField = value"

ng-show="orderByField == value"

而且ng-repeat 指令还创建了自己的隔离$scope。因此,在指令内分配一个变量会在 $scope 内创建变量。

作为一种解决方案 - 在 $scope 中添加一个函数来分配这些字段,然后在 ng-click 上调用它

或使用$parent 对象访问变量

ng-click="$parent.orderByField = value; $parent.reverseSort = !$parent.reverseSort"

【讨论】:

  • 在这里使用 $parent.* 是可行的,但从可维护性/可读性的角度来看,它是非常不受欢迎的。请参阅我在答案中链接的有关“控制器为”的文章
【解决方案3】:

您可以在 Controller 中创建一个函数并调用它并传递 value 作为参数。

例子:

$scope.changeSort = function(val) {
  $scope.orderByField = val;
  $scope.reverseSort = !$scope.reverseSort;
}

在您的 HTML 中:

<th style="width:100px;font-weight:bold;cursor:pointer" 
    ng-repeat="value in field_names" ng-click="changeSort(value);">
    {{value}}  <span ng-show="orderByField == '{{value}}'">
        <span ng-show="!reverseSort">^</span>
        <span ng-show="reverseSort">v</span>
    </span>
</th>

更新:

我写了一个 plunker 来显示我的建议,包括向上和向下箭头。

http://plnkr.co/W2vElBasnmRzYie2sZE1

【讨论】:

  • 谢谢...您的代码运行良好!!!!我想知道为什么有必要在这里创建一个函数以及为什么 {{value}} 不起作用....因为当我检查 chrome 中的元素时,工作表的 HTML 和不工作表的 HTML 是相同的......无论如何,谢谢...您的代码有效,因此您很棒!!!
  • 因为在写值之前代码已经被angular编译过了
  • 哇...我想知道这意味着什么...你有一个链接可以让我学习和理解角度的流程吗...例如何时调用编译器以及何时调用值处理......
  • 你应该看看编译器服务页面:docs.angularjs.org/guide/compiler 记得将答案标记为有效以帮助其他用户。
  • 您的投票需要 15 声望才能公开。但我不确定,但我认为您作为问题所有者可以将答案标记为正确。不确定..我是新来的。 :) 谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-09
相关资源
最近更新 更多