0

I hate it when I repeat code. So I want to know if there is a better way of doing this. I have 2 directives, they are very simple and very similar. The 2 directives look like this:

.directive('pkFilterProducts', function () {
    return {
        restrict: 'A',
        templateUrl: 'assets/templates/directives/pkFilterProducts.html',
        scope: {
            products: '=pkFilterProducts',
            filters: '='
        }
    }
})

.directive('pkStateProducts', function () {
    return {
        restrict: 'A',
        templateUrl: 'assets/templates/directives/pkStateProducts.html',
        scope: {
            products: '=pkStateProducts',
            states: '='
        }
    }
})

The only difference is one accepts filters and the other accepts states. The templates are very similar too:

<div class="col-md-6">
    <h3>Excluded ({{ excluded.length }})</h3>

    <div class="table-responsive" ng-show="excluded.length">
        <table class="table table-hover">
            <thead>
                <tr>
                    <th class="image-column"></th>
                    <th>Title</th>
                </tr>
            </thead>
            <tbody>
                <tr ng-repeat="product in products | exclude: filters as excluded">
                    <td><img class="img-responsive" ng-src="{{ product.image }}" /></td>
                    <td>{{ product.shortTitle }}</td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

<div class="col-md-6">
    <h3>Included ({{ included.length }})</h3>

    <div class="table-responsive" ng-show="included.length">
        <table class="table table-hover">
            <thead>
                <tr>
                    <th class="image-column"></th>
                    <th>Title</th>
                </tr>
            </thead>
            <tbody>
                <tr ng-repeat="product in products | include: filters as included">
                    <td><img class="img-responsive" ng-src="{{ product.image }}" /></td>
                    <td>{{ product.shortTitle }}</td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

and

<div class="col-md-6">
    <h3>Excluded ({{ excluded.length }})</h3>

    <div class="table-responsive" ng-show="excluded.length">
        <table class="table table-hover">
            <thead>
                <tr>
                    <th class="image-column"></th>
                    <th>Title</th>
                </tr>
            </thead>
            <tbody>
                <tr ng-repeat="product in products | statesExclude: states as excluded">
                    <td><img class="img-responsive" ng-src="{{ product.image }}" /></td>
                    <td>{{ product.shortTitle }}</td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

<div class="col-md-6">
    <h3>Included ({{ included.length }})</h3>

    <div class="table-responsive" ng-show="included.length">
        <table class="table table-hover">
            <thead>
                <tr>
                    <th class="image-column"></th>
                    <th>Title</th>
                </tr>
            </thead>
            <tbody>
                <tr ng-repeat="product in products | statesInclude: states as included">
                    <td><img class="img-responsive" ng-src="{{ product.image }}" /></td>
                    <td>{{ product.shortTitle }}</td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

again, the only different is the ng-repeat filter. Instead of using include or exclude it uses statesInclude and statesExclude. Is there a way I can combine these too? Maybe use a variable for the filter?

r3plica
  • 13,017
  • 23
  • 128
  • 290
  • You can't use a variable for the filter. Unless you want to refactor filters and create custom filter that accepts 'mode' parameter and aggregates `include` and `stateInclude`, then no, there's no way. And tbh, the code doesn't cry for refactoring, I see no reason to ruin it with messy common denominator. – Estus Flask Jun 14 '16 at 12:59
  • http://stackoverflow.com/questions/26710513/angular-filter-name-as-variable shows using filternames as variables – r3plica Jun 14 '16 at 13:51
  • It is essentially the same thing as custom filter, just more awkward. – Estus Flask Jun 14 '16 at 14:04

2 Answers2

1

It might sound a bit too hacky but I'd join the two ng-repeats on a single template and use ng-ifs to make them check for which is valid/should run. Example:

<tr ng-if="states"
    ng-repeat="product in products | statesInclude: states as included">
    <td><img class="img-responsive" ng-src="{{ product.image }}" /></td>
    <td>{{ product.shortTitle }}</td>
</tr>
<tr ng-if="filters"
    ng-repeat="product in products | include: filters as included">
    <td><img class="img-responsive" ng-src="{{ product.image }}" /></td>
    <td>{{ product.shortTitle }}</td>
</tr>

You could then perhaps use a single directive declaration:

.directive('pkProducts', function () {
    return {
        restrict: 'A',
        templateUrl: 'assets/templates/directives/pkProducts.html',
        scope: {
            products: '=pkFilterProducts',
            filters: '=',
            states: '='
        }
    }
})
0

I agree with wdanda.

Another solution would be to pass an boolean to your filter. Depending on the boolean you need to make it behave different.

See this for reference.

Community
  • 1
  • 1
b-pos465
  • 131
  • 4