Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically filter ng-repeat on ng-click

I'm building an app at http://creditcardairlinepoints.com and I want the user to be able to filter an array of credit cards by clicking a filter on the side of the interface e.g. only Amex cards, cards with no fee.

I'm able to bind the filter function to the user clicking the filter, but the function itself doesn't work as planned. There are two problems:

  1. I can't seem to get the filter to default to null. One of the links is to display 'all cards' which works on click, by setting the filter to null but I can't get this to on page load.
  2. I need to dynamically generate the filter e.g. cardFee:0, minSpend:0, bonusCurrency:amex and I'm not able to do this.

I'm wondering if I'm going about this the wrong way and rather than generate the filter based on variables passed in from the array via the front end I should setup a loop e.g.

  • if filterId = 0, do nothing
  • if filterId = 1, show amex cards

Filter list

The list of filter links generated from an array using ng-repeat. I've bound this successfully to the function below and can successfully pass values to it.

<ul class="nav nav-sidebar">
    <li ng-repeat="filter in filters" 
        ng-click="selectFilter($index);setFilter(filter.property, filter.value)" 
        ng-class="{active: $index===selectedIndex}">
        <a href="#">{{ filter.anchor }}</a>
    </li>
</ul>

Card Output

Cards output to table cells in a given row, this is what I'd like to filter on click.

<tr ng-repeat="card in cards | orderBy:predicate:reverse | filter:cardFilter">

Filter array

The card array works fine and if I code up any of these filters statically it works.

$scope.filters = [
    {
        'filterId': 0,
        'anchor': 'All cards',
        'property': '',
        'value': ''
    },
    {
        'filterId': 1,
        'anchor': 'American Express cards',
        'property': 'bonusCurrency',
        'value': 'amex'
    },
    {
        'filterId': 2,
        'anchor': 'Avios cards',
        'property': 'bonusCurrency',
        'value': 'avios'
    },
    {
        'filterId': 3,
        'anchor': 'No fee',
        'property': 'cardFee',
        'value': '0'
    },
    {
        'filterId': 4,
        'anchor': 'No minimum spend',
        'property': 'minSpend',
        'value': '0'
    }
];

Filter function

What I'm trying to achieve, a dynamically generated filter with a null default.

/* Set first filter link to default */
$scope.cardFilter = ''; 

$scope.setFilter = function ( k, v ) {
    $scope.cardFilter = {k:v};
};
like image 593
John Peden Avatar asked Dec 05 '25 09:12

John Peden


1 Answers

Got this working in the end by approaching the problem in a different way. I assigned each card object in the array a property 'status' of 1 by default. If the status value === 1, then it is shown in the DOM.

When a user clicks a filter, the ID of the link they've clicked is sent through to app.js which then updates the status property of all cards in the array, dependent on a small piece of logic associated with each link.

ng-if then iterates through the array and hides/shows elements dependent on their updated status.

Filter Links

<ul class="nav nav-sidebar">
    <li ng-repeat="filter in filters" ng-click="selectFilter($index);updateStatus(filter.filterId)" ng-class="{active: $index===selectedIndex}"><a href="#"></span>{{ filter.anchor }}</a></li>
</ul>

Table output

<tr ng-repeat="card in cards | orderBy:predicate:reverse" ng-if="cardFilter(card.cardStatus)">

Sample Card Object from cards array

{
        cardName: "American Express Preferred Rewards Gold",
        cardStatus: 1,
        cardBonus: 10000,
        cardBonusVisual: 10000,
        bonusValue: 100,
        bonusCurrency: "spg",
        bonusCurrencyVisual: "SPG points",
        cardFeeSymbol: "£",
        minSpendSymbol: "£",
        cardFee: 75,
        cardFeeVisual: "75",
        imageName: "spg.jpg", 
        minSpend: 1000,
        minSpendVisual: "1000",
        spendTimeLimit: 90,
        spendTimeLimitVisual: "90",
        spendTimeLimitDays: "days",
        cardURL: "https://www252.americanexpress.com/inga/uk/pers/begin.do?perform=IntlEapp:UK:triCredit&journey=B&intlink=uk-amex-cardshop-britishairwaysamericanexpresscreditcard-detail-applynow-main"
    }

Filters Array

$scope.filters = [
    {
        'filterId': 0,
        'anchor': 'All cards'
    },
    {
        'filterId': 1,
        'anchor': 'American Express cards'
    },
    {
        'filterId': 2,
        'anchor': 'Avios cards'
    },
    {
        'filterId': 3,
        'anchor': 'No fee'
    },
    {
        'filterId': 4,
        'anchor': 'No minimum spend'
    }
];

Function to hide/show cards in table

$scope.cardFilter = function(cardStatus){
    if(cardStatus === 1){
       return true;
    }
    return false;
}
like image 165
John Peden Avatar answered Dec 07 '25 21:12

John Peden



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!