Search code examples
angularjsangularjs-filterangular-filters

How to go about "binding" table rows together in angular?


I have a project where i need to display a list of comments and replies to a document. Each comment is to a specific revision of the document, and the comment chains should stay together in the table. I have achieved this by sorting the document first by the comment chain number, then by id, so the newest comments are last in the chain, this works as intended (see picture, green lines belong to the row above them) desired outcome

Now the problem is if i wanna manipulate the table in any way, i need still need the rows to stay in this order.

Lets say i want to search for some word in a comment, i would like to not only see the row with the result, but the entire comment chain of rows that belong together.

If i search for Lorem in the picture, i would get only the row with lorem, but i would like the next 2 aswell seeing as how they are reponses to the first row.

I am using angular and was thinking that the solution might be writing a custom filter.

Is there any way to "bind" the rows together?

<table class="table table-bordered" style="text-align: center;">
            <thead>
                <tr>
                    <th>Unit no.</th>
                    <th>Item ref.</th>
                    <th>Rev.</th>
                    <th>Comment (client)</th>
                    <th>Response (XXX)</th>
                    <th>Code</th>
                    <th>Responsible</th>
                    <th>Closed in rev.</th>
                </tr>
            </thead>
            <tbody>
                <tr ng-repeat="com in Document.Comments | filter:search" ng-class="{'active': com.ParrentCommentId != 0, 'success': com.ParentCommentId >0}">
                    <td>{{com.ParentCommentId == 0 ? com.UnitNumber : "-"}}</td>
                    <td>{{com.ParentCommentId == 0 ? com.ItemRef : "-"}}</td>
                    <td>{{com.Revision}}</td>
                    <td>{{com.Comment}}</td>
                    <td>{{com.Response}}</td>
                    <td>{{com.ParentCommentId == 0 ? com.Code : "-"}}</td>
                    <td>{{com.ParentCommentId == 0 ? com.Responsible : "-"}}</td>
                    <td>{{com.ClosedInRevision}}</td>
                </tr>
            </tbody>
        </table>

I store the id of the parentcomment if the comment belongs to a chain, so the only difference is that if the parentCommentId field is 0, the comment is a top level parent.


Solution

  • I fixed this by instead of storing all the rows in a list, i made a list of lists containing the rows. Then i used ng-repeat-start to include another ng-repeat of tr below the first object in each array. So that if a top level comment had children, these would get a row beneath it.

    <table class="table table-bordered" style="text-align: center;">
                <thead>
                    <tr>
                        <th>Unit no.</th>
                        <th>Item ref.</th>
                        <th>Rev.</th>
                        <th>Comment (client)</th>
                        <th>Response (XXX)</th>
                        <th>Code</th>
                        <th>Responsible</th>
                        <th>Closed in rev.</th>
                    </tr>
                </thead>
                <tbody>
                    <tr ng-repeat-start="com in Document.Comments  | filterComment:search.Comment" class="active">
                        <td>{{com[0].UnitNumber}}</td>
                        <td>{{com[0].ItemRef}}</td>
                        <td>{{com[0].Revision}}</td>
                        <td>{{com[0].Comment}}</td>
                        <td>{{com[0].Response}}</td>
                        <td>{{com[0].Code}}</td>
                        <td>{{com[0].Responsible}}</td>
                        <td>{{com[0].ClosedInRevision}}</td>
                    </tr>
                    <tr ng-repeat-end ng-repeat="com2 in com" ng-if="!$first" class="success">
                        <td>-</td>
                        <td>-</td>
                        <td>{{com2.Revision}}</td>
                        <td>{{com2.Comment}}</td>
                        <td>{{com2.Response}}</td>
                        <td>-</td>
                        <td>-</td>
                        <td>{{com2.ClosedInRevision}}</td>
                    </tr>
                </tbody>
            </table>
    

    I then created a filter to handle the searching of comments

    app.filter("filterComment", function () {
    return function (items, searchText) {
        var filtered = [];
        if (!searchText)
            return items;
        angular.forEach(items, function (item) {
            var found = false;
            angular.forEach(item, function (commentClass) {
                if (!found && commentClass.Comment.toUpperCase().includes(searchText.toUpperCase())) {
                    filtered.push(item);
                    found = true;
                }
            });
        });
        return filtered;
    };
    });