0

I have been working on a demo shopping app using AngularJS where I want to be able to list products on the basket page and then sort the list based on some nutritional attributes. I have the sort feature working for each of the attributes, using ng-repeat to loop through the array of items and ng-click to sort the order of the items.

As a next step I want to show some additional information on a product when the list is sorted. Each time you sort the list I would like any products that exceed X in the attribute sorted by to be highlighted e.g. maybe a red background, and displays the actual figure. Anything below X should be displayed as normal. When the list is in its default view I wouldn’t want any of this formatting to be displayed.

The sort is triggered using the following dropdown:

<button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
    {{sortedBy}}
    <span class="caret"></span>
  </button>
  <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
     <li><a href="#" event-focus="click" data-value="unsorted" value="unsorted" event-focus-id="ProductID" ng-click="reload()">Default</a></li>
    <li><a href="#" event-focus="click" data-value="Energy" value="Energy" event-focus-id="ProductID" ng-click="order('HealthStats.Energy')">Energy</a></li>
    <li><a  href="#" event-focus="click" data-value="fat" event-focus-id="ProductID" ng-click="order('HealthStats.Fat')">Fat</a></li>
    <li><a href="#" event-focus="click" data-value="saturates" event-focus-id="ProductID" ng-click="order('HealthStats.Saturates')">Saturates</a></li>
    <li><a href="#" event-focus="click" data-value="sugar" event-focus-id="ProductID" ng-click="order('HealthStats.Sugar')">Sugar</a></li>
    <li><a href="#" event-focus="click" event-focus-id="ProductID" ng-click="order('HealthStats.Salt')" data-value="salt">Salt</a></li>
  </ul>

The sort uses the following controller:

app.controller('sortAttribute', function($scope, $http, localStorageService) {  
$scope.basketID = localStorageService.get('basketID');
console.log($scope.basketID);

 $http.get("../api/BasketService?basketId=" +    $scope.basketID)
        .then(function(response){ 
            $scope.products = response.data.BasketContentItemList; 
        })

$scope.predicate = ProductID;
$scope.sortedBy = 'Sort Basket By:'
$scope.reverse = false;
$scope.order = function(predicate) {
$scope.reverse = true; 
$scope.predicate = predicate;
$scope.sortedBy = predicate.substr(12, predicate.length);
};

** I have removed parts of the controller that aren’t relevant

This ng-repeat then prints the product name, quantity, price and image:

    <div class = "product-list-info-container"  ng-repeat="product in products | orderBy:predicate:reverse"     >

      <div class = "product-image">
            <span class="label label-primary"></span><img ng-src="{{ product.ImageUrl }}" />
      </div>
        <div class="product-name">
            <span ng-style="set_color(attribute)" class="label label-primary" ><!--Description :--></span><p> {{ product.ProductName }} x {{ product.Quantity }}</p>
        </div>
        <div class="product-price">
            <span class="label label-primary"><!--Description :--></span><p> £{{ product.ProductPrice}}</p>
        </div>
    </div>

The products are returned in this format:

{
"BasketContents": {
    "BasketContentItemList": {
        "ProductInformation": [
            {
                "ProductID": "3257340",
                "HealthStats": {
                    "Energy": "30",
                    "Fat": "0.1",
                    "Salt": "0.1",
                    "Saturates": "0.1",
                    "Sugar": "6"
                },
                "ImageUrl": "../images/340_0000003257340_IDShot_90x90.jpg",
                "ProductName": "Strawberries",
                "ProductPrice": "2.00",
                "Quantity": "1",
                "QuantityOfUnit": "400",
                "UnitOfMeasurement": "G"
            },
            {
                "ProductID": "3250075",
                "HealthStats": {
                    "Energy": "198",
                    "Fat": "19.5",
                    "Salt": "0",
                    "Saturates": "4.1",
                    "Sugar": "0.5"
                },
                "ImageUrl": "../images/075_0000003250075_IDShot_90x90.jpg",
                "ProductName": "AVOCADOS",
                "ProductPrice": "1.75",
                "Quantity": "1",
                "QuantityOfUnit": "1",
                "UnitOfMeasurement": "SNGL"
            }

I have been researching different ways to change the styling based on a value within the array but so far the only the thing I have found that can be used in conjunction with ng-repeat is $first – however this is not suitable as this means the styling is always applied to the first product in the list even if it doesn’t exceed the required value.

TLDR; does anyone know how I can apply conditional formatting to items within an ng-repeat based on a value within the array?

1 Answer 1

2

Have a look at the ngClass directive, it will allow you conditionally apply classes based on a model.

This example will apply the class highlight when the product price is greater than 200. (I would also recommend not storing all of your values in the model as string when there are other data types that fit better)

<div ng-class="{highlight: product.ProductPrice > 200}" class = "product-list-info-container"  ng-repeat="product in products | orderBy:predicate:reverse"     >
  <div class = "product-image">
    <span class="label label-primary"></span><img ng-src="{{ product.ImageUrl }}" />
  </div>
  <div class="product-name">
    <span ng-style="set_color(attribute)" class="label label-primary" ><!--Description :--></span><p> {{ product.ProductName }} x {{ product.Quantity }}</p>
  </div>
  <div class="product-price">
    <span class="label label-primary"><!--Description :--></span><p> £{{ product.ProductPrice}}</p>
  </div>
</div>
Sign up to request clarification or add additional context in comments.

2 Comments

This is really helpful thank you, I have been able to style the products based on their nutritional attributes. However at the moment this is applied to products regardless of which sort is applied to the list. Ideally I only want to format products when we are sorting the list on that attribute, so high fat products are only highlighted when the list is sorted by fat, is that possible?
sure is. try ng-class="{highlight: product[sortedBy] > 200}"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.