3

I have one object like this

$scope.listvalues = [{ name:A, id:101 },

                     { name:B, id:102 },

                     { name:A, id:103 },

                     { name:C, id:101 },

                     { name:A, id:102 },

                     { name:B, id:103 }];

I need to print this object in following structure

name |101 | 102 |103 |
-----|----|-----|---------
 A   |YES | YES |YES |
-----|----|-----|------------
 B   |No  | YES |YES |
-----|----|-----|-----------
 C   |YES |  NO |NO  |

Here i need to print the Name "A" in unique and also need to indicate the A is available for which Id. Is it possible to do with angularjs ng-repeat?. Any one please suggest...

4
  • i don't think you should use ng-repeat in such scenario Commented Apr 23, 2015 at 11:48
  • 1
    It is possible, but you should format your data in a better way before. It'll be easier and more understandable Commented Apr 23, 2015 at 11:52
  • then how can we print the object values in above format. If the object is larger any way we need to use the ng-repeat is it right?? Commented Apr 23, 2015 at 11:54
  • All solutions below suffer from performance/memory issues, especially when the table is sparse. I would rather write a custom directive to handle this case and add watcher for possible bindings. Commented Apr 23, 2015 at 12:45

3 Answers 3

1

You can, but you would have to write a filter that changes the structure of your data to the following:

$scope.data = [
    {A: {'101': true, '102': true, '103': true}}, 
    {B: {'101': false, ...}},
    {C: ...}
]

And then you can write your table like this:

   <table>
     <tr>
       <th>name</th>
       <th ng-repeat="(column, value) in data[0]">{{column}}</th>
     </tr>
     <tr ng-repeat="row in data">
       <td ng-repeat="(column, value) in data[0]">{{row[column] ? 'Yes' : 'No'}}</td>
     </tr>
   </table>

Example filter:

yourModule.filter('makeNgRepeatable', function(){
    return function(oldStructure) {
       // Add code here to convert oldStructure to newStructure.
       return newStructure;
    }
});

In your controller, inject makeNgRepeatableFilter and do

$scope.data = makeNgRepeatableFilter([{ name:A, id:101 }, ...]);
Sign up to request clarification or add additional context in comments.

8 Comments

Can you please give one example for filtering the data to the proper format?
Added an example filter.
Why do you want to implement a filter for this? Is the map function not sufficient?
@Rouby You could do this in multiple ways, I chose a filter because it's the Angular way of doing it. A separate filter allows easier unit testing of your app.
filter - Selects a subset of items from array and returns it as a new array. ... well kinda :p
|
0

You can pack this into a table and then resolve with multiple ng-repeats which cell is YES or NO.

Take a look at this plnkr, it demonstrates how this could be achieved.

http://plnkr.co/edit/QI8ZrsbwYuJUeV4DNWGl?p=preview

First you collect all distinct ids and names.

$scope.names = $scope.listvalues.map(function(d){return d.name}).unique();
$scope.ids = $scope.listvalues.map(function(d){return d.id}).unique();

Note: In the plnkr I defined the functions unique and contains. If you use some other libraries like underscore those functions may already be present.

Then you define a function to determine if a specific cell should be true or false.

  $scope.hasValue = function(name, id)  {
    for(var i = 0; i < $scope.listvalues.length; ++i)
      if($scope.listvalues[i].name === name && $scope.listvalues[i].id === id)
        return true;
    return false;
  }

However, it would be simpler if you can convert your listvalues into a reasonable structure. This would prevent some of the overhead.

Comments

0

With your array structure you might need some additional helper array/objects. In your case it could look like this:

<table class="table table-bordered">
    <thead>
        <tr>
            <th>Name</th>
            <th ng-repeat="th in values">{{th}}</th>
        </tr>
    </thead>
    <tbody>
        <tr ng-repeat="obj in names">
            <td>
                {{obj.name}}
                <div><small>{{obj}}</small></div>
            </td>
            <td>{{obj.ids.indexOf(values[0]) > -1 ? 'YES' : 'NO'}}</td>
            <td>{{obj.ids.indexOf(values[1]) > -1 ? 'YES' : 'NO'}}</td>
            <td>{{obj.ids.indexOf(values[2]) > -1 ? 'YES' : 'NO'}}</td>
        </tr>
    </tbody>
</table>

where helper objects are constructed like:

function initData() {

    var map = {values: {}, names: {}},
        values = [],
        names = [];

    $scope.listvalues.forEach(function(obj) {
        if (!map.values[obj.id]) {
            values.push(obj.id);
            map.values[obj.id] = true;
        }

        if (!map.names[obj.name]) {
            names.push(obj);
            obj.ids = [obj.id];
            map.names[obj.name] = obj;
        }
        else {
            map.names[obj.name].ids.push(obj.id);
        }
    });

    $scope.values = values;
    $scope.names = names;
}

initData();

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.