dascalos
dascalos

Reputation: 509

Angular bind table to cross data

Basically I am trying to two-way bind to a table of values based on the intersection of point in the table.

I've set up a plnkr of what I am trying to achieve here...

Angular Bind To Value Table

So given this set of data...

$scope.beers = [
{ id: 27, description: "Hopslam Ale" },
{ id: 28, description: "Founders Kentucky Breakfast Stout" },
{ id: 29, description: "Zombie Dust" } ];

$scope.characteristics = [
{ id: 3, description: "ABV" },
{ id: 4, description: "IBU" },
{ id: 5, description: "Calories" },
{ id: 6, description: "Reviews"}];

$scope.crossData = [
{ beerId: 27, characteristicId: 3, value: 10 },
{ beerId: 27, characteristicId: 4, value: 70 },
{ beerId: 27, characteristicId: 5, value: 300 },
{ beerId: 27, characteristicId: 6, value: 3419 },
{ beerId: 28, characteristicId: 3, value: 11 },
{ beerId: 28, characteristicId: 4, value: 70 },
{ beerId: 28, characteristicId: 5, value: 336 },
{ beerId: 28, characteristicId: 6, value: 2949 },
{ beerId: 29, characteristicId: 3, value: 6 },
{ beerId: 29, characteristicId: 4, value: 50 },
{ beerId: 29, characteristicId: 5, value: 186 },
{ beerId: 29, characteristicId: 6, value: 1454 }];

How can I two-way bind to the value in the cross data?

<table class="table table-striped">
  <thead>
    <tr>
      <th>#</th>
      <th ng-repeat="char in characteristics">
        {{ char.description }}
      </th>
    </tr>
  </thead>
  <tbody>
    <tr ng-repeat="beer in beers">
      <td>{{ beer.description }}</td>
      <td ng-repeat="char in characteristics">
        <!-- some kind of binding expression here -->
      </td>
    </tr>
  </tbody>
</table>

Any help would be greatly appreciated.

Upvotes: 1

Views: 3031

Answers (3)

Bruno Jo&#227;o
Bruno Jo&#227;o

Reputation: 5535

Sorry for my last answer. I did not notice the two way data bind need.

So, I've found two solutions

1 - This one filter the crossData on the html: http://plnkr.co/edit/M1rnx6IJqJ95apJJ55iN

<tbody>
  <tr ng-repeat="beer in beers">
    <td>{{ beer.description }}</td>
    <td ng-repeat="char in characteristics">
      <input ng-model="(crossData | filter:{beerId: beer.id, characteristicId: char.id})[0].value"/>
    </td>
  </tr>
</tbody>

2 - This one uses a function to filter the crossData: http://plnkr.co/edit/MHQy31rqZMg2TXYn0P23

What I did was Add a function to return the object of the crossData list. The function is as follow:

$scope.getCrossDataRow = function(beerId, charId){
    return $filter('filter')($scope.crossData, {beerId: beerId, characteristicId: charId})[0];
};

Do not forget to load the $filter in your controller.

Finally, you can use this function in your table row to bind the value as follow:

<td ng-repeat="char in characteristics">
    <input type="text" ng-model="getCrossDataRow(beer.id, char.id).value" />
</td>

Upvotes: 1

kabaehr
kabaehr

Reputation: 1040

You could do this with this expression:

<span ng-repeat="cross in crossData" ng-if="cross.beerId === beer.id && cross.characteristicId === char.id">{{cross.value}}</span>

But it would be better if you had another data structure, but i guess you have no influence on this?

Upvotes: 0

fikkatra
fikkatra

Reputation: 5792

You can write a 'matching' function in the controller like this (current implementation just returns the first match):

 $scope.findMatch = function(beer, characteristic) {
    return $scope.crossData.filter(function(data) {
      return data.beerId === beer.id && data.characteristicId === characteristic.id
    })[0];
  }

Working code snippet:

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

app.controller('MainCtrl', function($scope) {

  $scope.beers = [
    { id: 27, description: "Hopslam Ale" },
    { id: 28, description: "Founders Kentucky Breakfast Stout" },
    { id: 29, description: "Zombie Dust" } ];
    
  $scope.characteristics = [
    { id: 3, description: "ABV" },
    { id: 4, description: "IBU" },
    { id: 5, description: "Calories" },
    { id: 6, description: "Reviews"}];
  
  $scope.crossData = [
    { beerId: 27, characteristicId: 3, value: 10 },
    { beerId: 27, characteristicId: 4, value: 70 },
    { beerId: 27, characteristicId: 5, value: 300 },
    { beerId: 27, characteristicId: 6, value: 3419 },
    { beerId: 28, characteristicId: 3, value: 11 },
    { beerId: 28, characteristicId: 4, value: 70 },
    { beerId: 28, characteristicId: 5, value: 336 },
    { beerId: 28, characteristicId: 6, value: 2949 },
    { beerId: 29, characteristicId: 3, value: 6 },
    { beerId: 29, characteristicId: 4, value: 50 },
    { beerId: 29, characteristicId: 5, value: 186 },
    { beerId: 29, characteristicId: 6, value: 1454 }];
  
  $scope.name = 'Stack Overflow friends';

  $scope.findMatch = function(beer, characteristic) {
    return $scope.crossData.filter(function(data) {
      return data.beerId === beer.id && data.characteristicId === characteristic.id
    })[0];
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="plunker" ng-controller="MainCtrl">
  <p>Hello {{name}}!</p>
  <br />
  <table class="table table-striped">
    <thead>
      <tr>
        <th>#</th>
        <th ng-repeat="char in characteristics">
          {{ char.description }}
        </th>
      </tr>
    </thead>
    <tbody>
      <tr ng-repeat="beer in beers">
        <td>{{ beer.description }}</td>
        <td ng-repeat="char in characteristics">
          {{findMatch(beer, char).value}}
        </td>
      </tr>
    </tbody>
  </table>
</body>

Upvotes: 0

Related Questions