mattiash/angular-tablesort

ts-repeat-start ts-repeat-end problem

YoavNordmann opened this issue · 7 comments

Hi

Foer some reason I cannot use the ts-repeat-start ts-repeat-end tags.

I get the following error:
Error: [$compile:uterdir] http://errors.angularjs.org/1.4.2/$compile/uterdir?p0=ts-repeat-start&p1=ts-repeat-end

And the relevant code is:

<table class="table table-condensed table-bordered table-striped" ts-wrapper>
    <thead>
        <tr>
            <th></th>
            <th ts-criteria="id">Transaction #</th>
            <th ts-criteria="completionDate|date">Date</th>
            <th ts-criteria="userId">User</th>
        </tr>
    </thead>
    <tbody>
        <tr ng-repeat-start="row in ctrl.exchangeTransactions | filter:ctrl.searchString" ts-repeat-start>
            <td>
              <button ng-if="row.expanded" ng-click="row.expanded = false">-</button>
              <button ng-if="!row.expanded" ng-click="row.expanded = true">+</button>
            </td>
            <td>{{row.id}}</td>
            <td ng-bind="row.completionDate | date"></td>
            <td>{{row.userId}}</td>
        </tr>
        <tr ng-if="row.expanded" ng-repeat-end=""  ts-repeat-end>
            <td colspan="4">We shall see this</td>
        </tr>
    </tbody>
</table>

Could you help me out here ?

Thanks

I think the problem ist the ng-if directive used with ng-repeat-end / ts-repeat-end. If "row.expanded" is false the dom element will not exist, and therefore there is also no ng-repeat-end or ts-repeat-end. Try using ng-show, ng-hide instead.

Thanks for the prompt response.
You are right. I am using ng-hide now and it truly works... untill:
I want more information in the hidden row. As soon as I insert a DIV or another TABLE inside the hidden row (instead of the text "We shall see this") the data (including the HTML tags) is nowhere to be found. SImple text works...
I tested this of course without the ts-repeat-start/end tags and it works as expected.
Any thoughts on that ?

@YoavNordmann Can you post an updated example?

Updated example of the code

<table class="table table-condensed table-bordered table-striped" ts-wrapper>
    <thead>
        <tr>
            <th></th>
            <th ts-criteria="id">Transaction #</th>
            <th ts-criteria="completionDate|date">Date</th>
            <th ts-criteria="userId">User</th>
        </tr>
    </thead>
    <tbody>
        <tr ng-repeat-start="row in ctrl.exchangeTransactions | filter:ctrl.searchString" ts-repeat-start>
            <td>
              <button ng-if="row.expanded" ng-click="row.expanded = false">-</button>
              <button ng-if="!row.expanded" ng-click="row.expanded = true">+</button>
            </td>
            <td>{{row.id}}</td>
            <td ng-bind="row.completionDate | date"></td>
            <td>{{row.locationId}}</td>
            <td>{{row.userId}}</td>
            <td>{{row.primaryCustomerId}}</td>
        </tr>
        <tr ng-show="row.expanded" ng-repeat-end="" ts-repeat-end>
            <td colspan="4">
                <table class="table table-condensed table-striped" ng-repeat="details in row.exchangeStatements">
                    <tr>
                        <td>Register: </td>
                        <td>{{details.registerId}}</td>
                    </tr>
                    <tr>
                        <td>Rate: </td>
                        <td>{{details.rate}}</td>
                    </tr>
                    <tr>
                        <td colspan="2"> </td>
                    </tr>
                </table>
            </td>
        </tr>
    </tbody>
</table>

Unfortunately, the way that ts-repeat has to alter the compilation of the DOM alongside ng-repeat makes compilation of nested ng-repeat not function correctly. I have a very similar situation and my solution was to make the nested table a separate custom element directive which will get compiled correctly. In your case you'd have something like a <exchange-state-table>...</exchange-state-table> directive inside your expandable row. The added benefit is that you can make the sub-table ts-sortable as well.

Wow... this sucks !
This module is so small and sweet, exactly what I am looking for...
I would like to know if there is a possibility for a fix in the near future before I downgrade my stuff to a simple filtering solution.

Thank you very much for your help, I love your work !

Yoav

It really only affects the the ts-repeat-end with nested ng-repeat situation. I tried to figure it out (disclosure: I'm the one who added the multi-element support to this module), but somebody smarter than me will have to take a look and see if it can be fixed 😕.
It's really not that big a deal to make a simple directive of your own to workaround this issue (also good design to make more modular elements). Here's an example of one of mine I made to work around this and still get to use the awesome functionality of angular-tablesort:

Directive

.directive('transactionsTable', ['COMPONENTS_ROOT', function (COMPONENTS_ROOT) {
        return {
            restrict: 'E',
            templateUrl: COMPONENTS_ROOT + 'contacts/templates/transactions-table.html',
            link: function (scope, elem, attrs) {
                scope.transactions = [];
                scope.transactions = scope.$eval(attrs.transactions);
            },
            controller: ['$scope', function ($scope) {
                $scope.getTransactionTotal = function () {
                    if (!$scope.transactions) return 0;

                    var total = 0, i = 0, amount;

                    for (; i < $scope.transactions.length; i++) {
                        amount = parseFloat($scope.transactions[i].TransactionTotal);
                        total += amount || 0;
                    }

                    return total;
                };
            }]
        };
    }])

Directive Template (edited for brevity)

<table ts-wrapper>
    <thead>
        <tr>
            <th class="col-xs-2" ts-criteria="TransactionDate" ts-default>{{'DATE' | translate}}</th>
            <th class="col-xs-2" ts-criteria="FiscalYear">{{'FINANCIAL_YEAR' | translate}}</th>
            <th class="col-xs-3" ts-criteria="Reference">{{'REFERENCE' | translate}}</th>
            <th class="col-xs-3" ts-criteria="Memo">{{'MEMO' | translate}}</th>
            <th class="col-xs-2 align-right" ts-criteria="TransactionTotal | parseFloat">{{'AMOUNT' | translate}}</th>
        </tr>
    </thead>
    <tbody>
        <tr ng-repeat="transaction in transactions"  ts-repeat>
            <td>{{::transaction.TransactionDate | date:DATE_FORMAT}}</td>
            <td>{{::transaction.FiscalYear}}</td>
            <td>{{::transaction.Reference}}</td>
            <td>{{::transaction.Memo}}</td>
            <td class="align-right">{{::transaction.TransactionTotal | absValue | currency}}</td>
        </tr>
    </tbody>
    <tfoot>
        <tr>
            <td class="align-right" colspan="4"><strong>{{'TOTAL' | translate}}:</strong></td>
            <td class="align-right"><strong>{{getTransactionTotal() | absValue | currency}}</strong></td>
        </tr>
    </tfoot>
</table>

Outer template (edited for brevity)

<table ts-wrapper>
        <thead>
            <tr>
                <th class="col-xs-1">
                    ...
                </th>
                <th class="col-xs-2" ts-criteria="CustomId">{{'ID' | translate}}</th>
                <th class="col-xs-3" ts-criteria="ui.lastNameFirstName | lowercase" ts-default>{{'NAME' | translate}}</th>
                <th class="col-xs-4" ts-criteria="ui.preferred.addresses.labelFormat()">{{'ADDRESS' | translate}}</th>
                <th class="col-xs-2 align-right" ts-criteria="ui.getTotal1099Transactions() | parseFloat">{{'TOTAL' | translate}}</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat-start="contact in filteredList" ts-repeat-start>
                <td>
                    ...
                </td>
                <td>{{::contact.CustomId}}</td>
                <td>{{::contact.ui.lastNameFirstName}}</td>
                <td ng-bind-html="..."></td>
                <td class="align-right">{{::contact.ui.getTotal1099Transactions() | currency}}</td>
            </tr>
            <tr ng-repeat-end uib-collapse="contact.ui.detailsAreCollapsed" ts-repeat-end>
                <td></td>
                <td colspan="4">
                    <transactions-table transactions="contact.transactions1099"></transactions-table>
                </td>
            </tr>
        </tbody>
        ...
    </table>