2

I need some help to render a html table using an Angular model.

First, I have a model that specifies that I need to render a table, and a list of the "questions" that needs to be shown in the table.

Data example:

   {

    "Id": 25546,
    "questionType": "Table",
    "maxRows": 2,
    "maxCols": 3,
    "questionsInTable": [{
        "isActive": true,
        "questionText": "Table Title",
        "validation": "false",
        "rowPosition": 1,
        "colPosition": 1,
        "isPrintable": true,
        "Answer": null,
        "Type": "Label"
    }, {
        "isActive": true,
        "questionText": "2014",
        "validation": "false",
        "rowPosition": 1,
        "colPosition": 2,
        "isPrintable": true,
        "Answer": null,
        "Type": "Label"
    }, {
        "isActive": true,
        "questionText": "2013",
        "validation": "false",
        "rowPosition": 1,
        "colPosition": 3,
        "isPrintable": true,
        "Answer": null,
        "Type": "Label"
    }, {
        "isActive": true,
        "questionText": "Another description here",
        "validation": "false",
        "rowPosition": 2,
        "colPosition": 1,
        "isPrintable": true,
        "Answer": null,
        "Type": "Label"
    }, {
        "isActive": true,
        "questionText": "DescFor2014",
        "validation": "true",
        "rowPosition": 2,
        "colPosition": 2,
        "isPrintable": true,
        "Answer": null,
        "Type": "InputText"
    }, {
        "isActive": true,
        "questionText": "DescFor2013",
        "parentQuestion": 25546,
        "validation": "true",
        "rowPosition": 2,
        "colPosition": 3,
        "isPrintable": true,
        "Answer": null,
        "Type": "InputText"
    }]
}

Each item (or question) is providing the row and column position in the table, also the data has two items with the Max of rows and columns. I'm able to create the table using MaxRows and MaxCols data, but I'm struggling to insert the question in the correct cell.

The result should be the example above:

Render output example:

<table>
<tr>
    <td>Table Title</td>
    <td>2014</td>
    <td>2013</td>
</tr>
    <tr>
        <td>Another description here</td>
        <td>DescFor2014</td>
        <td>DescFor2013</td>
    </tr>
</table>

Is there a way to perform this?.

I'll appreciate your help, or if you could point me in the right direction.

2 Answers 2

3

I have created a Plunkr for your solution - http://plnkr.co/edit/4vUm8yRiDKlTM8lnQH7E?p=preview.

To create the row/column for the table I have created 2 arrays - rows and columns.

      $scope.rows = [];
          for (var i=0;i<$scope.tableData.maxRows;i++) {
          $scope.rows.push(i);
      }

      $scope.cols = [];
          for (var i=0;i<$scope.tableData.maxCols;i++) {
          $scope.cols.push(i);
      }

The HTML has been kept as:

<table>
  <tr ng-repeat="i in rows">
    <td ng-repeat="j in cols">
      <div table-pos object="tableData.questionsInTable" row="i" col="j"></div>
    </td>
  </tr>
</table>

table-pos is a directive that will accept the questions array, row and column index as scope attributes. I have used underscore.js for extracting the correct object from the collection of questions and display question for that position (based on rowPosition and colPosition). The code looks like below:

.directive("tablePos", function() {
  return {
  template: "<div>{{data}}</div>",
  scope: {
    object: "=",
    row: "=",
    col:"="
  },
  link: function(scope) {
    var questions = scope.object; 
    var question= _.findWhere(questions, {colPosition:scope.col+1, rowPosition: scope.row+1});
    scope.data = question.questionText;
  }
  }
})

The main advantage of using the directive is that there is no requirement for the questions in the list to be sorted in any order. So you can add questions in any order in your array. As long as the rowPosition and colPosition has been defined correctly the directive will pick it up.
Plus the directive also supports empty cells/sparse arrays, so if any question for a particular cell is not present, the directive will show empty data.

One drawback is that, if more than 1 question have the same rowPosition and colPosition then only the first question will be picked, and the remaining questions will be silently ignored.

Please note that in case you don't want to use underscope.js, you can still use plain JavaScript to detect the correct question from the list. However, usage of underscore.js makes it easier, as the underlying logic is abstracted.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you!, I was trying to tweak the previous answer, but this works perfectly!
This could be a stupid question, I'm getting used to use directives, the question is, how could I bind the values from data to the original item in questionsInTable? see the follow Plunkr plnkr.co/edit/MB36ei2uqbow2IDh39ry?p=preview
2

Please refer to this Plunk: http://plnkr.co/edit/xTagjy1n9tl0CvnDH5Q3?p=preview

You basically have to ng-repeat the rows till maxRows and ng-repeat the cols till maxCols:

<table>
  <tr ng-repeat="i in [] | range:(tableData.maxRows)">
    <td ng-repeat="j in [] | range:(tableData.maxCols)">
      {{tableData.questionsInTable[j + i*tableData.maxCols].questionText}}
    </td>
  </tr>
</table>

Range is a filter function:

 angular.module('app').filter('range', function() {
  return function(input, total) {
    total = parseInt(total);
    for (var i=0; i<total; i++)
      input.push(i);
    return input;
  };
});

Note: This will only work when:

  1. the rows,cols pair are sorted. If not you will have to sort them first and then bind it to the table

  2. wont work for sparse arrays. In case of sparse arrays you will have to create dummy objects which should be ignored while creating the table

Also validate your JSON object in the question you posted before proceeding. It looks incorrect: http://jsonlint.com/

2 Comments

Thanks for your reply, but I saw that it shows only the first 3 items of the array in the table. I'm grateful that you have taken the time to give me this example, nevertheless, you have helped me.
you are right. i fixed the solution but the above solution given by Pratik is much better. upvoted that solution.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.