Push rows in a table rendered with ng-repeat in an

2019-03-11 12:47发布

问题:

I want to push in an extra row inline in a table when the client clicks on the row. The data should not be prefetched, since I expect there to be at most 30 rows but where each row has associated data that would be unreasonable to fetch in one get.

My approach so far is to use ng-repeat to iterate my collection and render a table. When the client presses the row, the client expects details about the row to be shown inline as an extra row under the pressed row.

<tr ng-repeat="court in courts">            
  <td>{{court.name}}</td>
  <td>{{court.number}}</td>
  <td>{{court.nrOfPlayers}}</td>
  <td>
    <a href ng:click="toggle(court.number)">Details</a>  <!-- click toggles extra row with data loaded async -->
  </td>
</tr>
<!-- extra row here -->

I have managed to show the details beneath the table with a ng-show in a hacky way, but that is not what I want.

How do you accomplish this with angular.js? What is the angular way to do this?

Here is a fiddle with a stupid squash court example http://jsfiddle.net/HByEv/

回答1:

I think a possible solution could be http://jsfiddle.net/HByEv/2/.

There is also an alternative for the "No players" message commented in the fiddle if you want to also get rid of the extra <tr ng-show="..."></tr>.

Edit:

As pointed in the comments, in AngularJS 1.2+ you can now use ng-repeat-start and ng-repeat-end to solve this problem.

Jossef Harush provided a fiddle: http://jsfiddle.net/3yamebfw/



回答2:

One sample

var app = angular.module('test-app', []);

app.controller('MyController', function($scope, $rootScope, $timeout){

    $scope.copy = {
        p1: ['c1 p1', 'c1 p2'],
        p3: ['c3 p1', 'c3 p2', 'c3 p3', 'c3 p4', 'c3 p5']
    }

    $scope.courts = [
        {
            "number": 1,
            "name": "the best court",
            "nrOfPlayers": 2
        }, {
            "number": 2,
            "name": "the bad court",
            "nrOfPlayers": 0
        }, {
            "number": 3,
            "name": "the other court",
            "nrOfPlayers": 5
        }
    ];

    $scope.loadPlayers = function(court){
        //Implement your logic here
        //Probably using ajax
        $timeout(function(){
            $scope.players = $scope.copy['p' + court.number] || [];
        }, Math.random() * 2000);
    }

    $scope.shouDetails = function(court){
        if(court.nrOfPlayers) {
            delete $scope.players;
            $scope.loadPlayers(court);
        } else {
            $scope.players = [];
        }
    }

})

Demo: Fiddle



回答3:

Well. In fact, the main issue with your design is that you want to show thousands of rows in the same table. It will work, but it might be hard to render in some browsers (IE). For each rows, you will have a few bindings and each binding add watchers. You should always try to minimize the amount of binding in the page. I suggest you to use a pagination system in your array. Pagination on a list using ng-repeat

If you really want to do what you want without prerendering the rows, you will have to edit the dom, which is not a good practice in angular when avoidable. In my case, i would place the data somewhere else on the page, in a static zone. When i did something like this, I added a twitter bootstrap modal in my page and when the user clicked on "more info" the modal was opened with the info of the selected object.