Frage

I'm using the MEAN stack and jade. I'm running into a problem with AngularJS using ng-repeat, ng-click, and orderby to sort columns in a table. It works fine as long as there is no space in the property name that is used for orderBy. The property name I'm having trouble with is "To Do".

I get this error in Chrome when I click the table header labeled "To Do": Error: Syntax Error: Token 'Do' is an unexpected token at column 4 of the expression [To Do] starting at [Do].

I have seen a couple other posts about trouble with accessing properties with a space. My issue is similar but I cannot get their solutions to work.

Jade: (This is how I have set up ng-click, orderBy, and ng-repeat. It works fine unless there is a space in the column)

table
  caption {{collectionName}}
  thead
    tr
      th(ng-repeat="column in columns" ng-click="setPredicate(column);")
        {{column}}
  tbody
    tr(ng-repeat="row in rows | orderBy:predicate:reverse")
      td(ng-repeat="column in columns")
        {{row[column]}}

Controllers.JS: (This is how Angular receives data for columns and rows. Also how ng-click changes the orderBy predicate)

$http.get('/api/collection/' + $routeParams.collectionName)
  .success(function(data){
    $scope.collection = data;
    $scope.columns = data.columns;
    $scope.rows = data.rows;
    console.log(data);
  });


$scope.setPredicate = function(column){
  if (column === "To Do"){
    var keys = Object.keys($scope.rows[0])
    $scope.predicate = keys[1]; 
    // $scope.predicate = "To Do"; 
    // $scope.predicate = column[$scope.columns];
  }else{
    $scope.predicate = column;
  }
  $scope.reverse = !$scope.reverse;
}

In the above code keys is equal to [ "_id", "To Do", "description", "due", "link", "$$hashKey"]. keys[1] is "To Do", which still does not work for the orderBy predicate. I tried other variations like the two commented out attempts above.

NodeJS index.JS: (This is how the columns array and the rows are sent to Angular after retrieving documents from MongoDB.)

router.get('/api/collection/:collectionName', function(req, res){
  collectionProvider.findCollection(req.param('collectionName'), function(error, documents){
    var keys;
    if(documents[0]){
      keys = Object.keys(documents[0]);
      remove(keys,'_id');
    }
    res.json({
      columns: keys,
      title: req.param('collectionName'),
      rows:documents,
      collectionName: req.param('collectionName')
    });
  });
});

To summarize, the column headings in my table are named after the property that represents the data in the column. I don't know which table will be pulled up or what columns it will have so node checks all the properties of the first record and sends an array of property names to $scope.columns. I use a predicate to switch the orderBy sorting to whichever column in $scope.columns gets clicked.

This is my first angular app. I originally expected to be able to use ng-click="predicate=column" in the Jade, but I was surprised to find out it did not work. That's why I'm sending to a controller function. I do not know if I'm going about this whole process the correct Angular way.

War es hilfreich?

Lösung

The orderBy predicate should be a function that is passed the collection, accesses the property by bracket notation and returns the value.

The setPredicate function in your case should set the value of the property that the predicate uses.

Try something like this:

JS:

// Default orderBy
$scope.orderBy = $scope.columns[0];

$scope.setOrderBy = function (column) {
  $scope.orderBy = column;
}

$scope.predicate = function(rows) {
  return rows[$scope.orderBy];
}

HTML:

<th ng-repeat="column in columns" ng-click="setOrderBy(column)">{{ column }}</th>

And:

<tr ng-repeat="row in rows | orderBy:predicate:reverse">

Demo: http://plnkr.co/edit/2Mlc2lBf0wRVicfcfYZO?p=preview

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top