Search code examples
javascriptangularjssplitline-breaksng-grid

Add multiple rows in ng-grid cell programatically


How can I add (programatically) multiple text rows in a ng-grid cell ?

The ng-grid is created in the following way:

HTML:

<div class="gridStyle" ng-grid="gridOptions"></div>

JavaScript:

$scope.gridOptions = {
    data: 'myArray',
    ...
}

where myArray is a JSON array created by me using something like this:

function returnJsonArray(size){
    var d = [];
    ...
    for ( var i = 0 ; i < size ; i++ ) {
        values = ['VALUE TO SPLIT', ...];
        d.push(createJsonObject(keys, values);
    }
    return d;
}

According to the above example there is "VALUE TO SPLIT" in every cell that is in the first column. I want to have:

+-------+-------+
| VALUE |       |
| TO    |   ?   |
| SPLIT |       |
+-------+-------+
| VALUE |       |
| TO    |   ?   |
| SPLIT |       |
+-------+-------+

instead of

+---------------+-------+
| VALUE TO SPLIT|   ?   |
+---------------+-------+
| VALUE TO SPLIT|   ?   |
+---------------+-------+

I tried to use <br/> (in values = ['VALUE<br/>TO<br/>SPLIT',...];), but it is considered to be part of my text.

By default, the resulted DOM contains a lot of divs:

...
    <div class="ngCellText col0 colt0" ng-class="col.colIndex()">                           
        <span ng-cell-text="" class="ng-binding">VALUE TO SPLIT</span>
    </div>
...

I am not interested in how the new output will be in DOM (it can use <span> + <br/> + <span> or <br/> can be in the middle of the text).


Solution

  • If you want dynamical row heights, ng-grid is not the best choice. It simulates a table layout with div grids that have a fixed height and are NOT measured at runtime. Better switch to a HTML table based solution like ng-table.

    Anyhow, regarding your question, this would be a solution:

    • Use fixed rowHeight in gridOptions to best match your largest rowHeight
    • Create a filter that replaces the spaces in the text <br>
    • Use a cellTemplate that uses that filter

    Here is a simple filter:

    app.filter('splitAtSpaces', function() {
      return function(text, length, end) {
        if (text) {
          return text.split(' ').join('<br>');
        }
      }
    });
    

    This is the cellTemplate:

    var splitTpl = '<div class="ngCellText" ng-bind-html="row.getProperty(col.field)|splitAtSpaces"></div>'
    

    And here are the gridOptions with best (guessed) height values:

      $scope.gridOptions = {
        data: 'myData',
        rowHeight: 90,
        columnDefs: [{
          field: 'name',
          displayName: 'Name',
          cellTemplate: splitTpl
        }, {
          field: 'age',
          displayName: 'Age'
        }]
      };
    

    And a plunker to show how everything works together.

    NOTE:

    • Look out for the inclusion and injection of ng-sanitize!
    • If you are using another version of angularJs ng-bind-html may be obsolete/not implemented (Aargh, I lost track of this security measures a while ago!) If your output shows <br> instead of doing an actual line break look around on SO. There are MANY more answers to this issue.

    Uhh, yes. I nearly forgot to tell you how to change the css so the divider fits your new rowHeight:

    .ngVerticalBar {
     height: 100%;
    }
    

    Come back with more detailed questions once you get this running. But overall I strongly suggest you use an other table/grid directive.