3
\$\begingroup\$

I used step 4 from the Angular tutorial to do some tinkering of my own. In that particular step of the tutorial, a option list is created that determines how a list is sorted (Alphabetically, by age). I tweaked the code to dynamically generate these sorting options from the data set.

Essentially, it takes the first element of the JSON data and creates a option for each of the keys:

<select ng-model="orderProp">
   <option value="{{opt}}" ng-repeat="(opt,value) in phones[0]">{{opt}}</option>
</select>

Any remarks or suggestions?

This is the full index.html file. The example is reproducible by installing the Angular tutorial.

<!doctype html>
<html lang="en" ng-app="phonecatApp">
<head>
  <meta charset="utf-8">
  <title>Google Phone Gallery</title>
  <link rel="stylesheet" href="css/app.css">
  <link rel="stylesheet" href="css/bootstrap.css">
  <script src="lib/angular/angular.js"></script>
  <script src="js/controllers.js"></script>
</head>
<body ng-controller="PhoneListCtrl">

  <div class="container-fluid">
    <div class="row-fluid">
      <div class="span2">
        <!--Sidebar content-->

        Search: <input ng-model="query">
        Sort by: 
        <select ng-model="orderProp">
            <option value="{{opt}}" ng-repeat="(opt,value) in phones[0]">{{opt}}</option>
        </select>

      </div>
      <div class="span10">
        <!--Body content-->

        <ul class="phones">
            <p> Now ordered by {{orderProp}} </p>
          <li ng-repeat="phone in phones | filter:query | orderBy:orderProp">
            {{phone.name}}
            <p>{{phone.snippet}}</p>
          </li>
        </ul>

      </div>
    </div>
  </div>

</body>
</html>

and the JSON data:

  $scope.phones = [
    {'name': 'Nexus S',
     'snippet': 'Fast just got faster with Nexus S.',
     'age': 1},
    {'name': 'Motorola XOOM™ with Wi-Fi',
     'snippet': 'The Next, Next Generation tablet.',
     'age': 2},
    {'name': 'MOTOROLA XOOM™',
     'snippet': 'The Next, Next Generation tablet.',
     'age': 3}
  ];
\$\endgroup\$
1
  • \$\begingroup\$ Is this code tested, specifically (opt,value) inside ng-repeat? \$\endgroup\$ – Dmitri Zaitsev Apr 19 '14 at 7:41
2
\$\begingroup\$

I think it's a bad idea for several reasons:

  • It is possible to have an empty data set in real-world app but it should not affect your sorting options in any way.
  • It is possible to have some optional fields or fields that aren't suit for sorting - images, additional description (original step-4 actually has such field) etc
  • You should have a full control over what you're displaying and being able to change it with ease.
  • Pretty titles instead of field names 'as is' look much better.
  • In case of a huge list of options you may need to group them using 'disabled' options as delimiters.

The main idea is to keep the balance between decoupling and ease of reusability and extensibility of your functionality. One of solutions is to create an object that describes the way particular data can be sorted. You can implement it as following, for example: http://jsfiddle.net/ocLrt7vp/

Adding sorting options to phones

$scope.phones =
{
    sorting: [
        {title:"---Name---", disabled:true},
        {sortQuery: "name", title: "By name: A-Z"},
        {sortQuery: "-name", title: "By name: Z-A"},
        {title:"---AGE---", disabled:true},
        {sortQuery: "-age", title: "New first"},
        {sortQuery: "age", title: "Old first"}
    ],
    data: [
        {'name': 'Nexus S',
            'snippet': 'Fast just got faster with Nexus S.',
            'age': 2010,
            androidVersion:"Unknown"},
        {'name': 'Motorola XOOM™ with Wi-Fi',
            'snippet': 'The Next, Next Generation tablet.',
            'age': 2012,
            weight: 708},
        {'name': 'MOTOROLA XOOM™',
            'snippet': 'The Next, Next Generation tablet.',
            'age': 2011}
    ]
};

And changing index.html as following

<div class="row">
  <div class="col-md-2">
    <!--Sidebar content-->

    Search: <input ng-model="query">
    Sort by:
      <select ng-model="orderProp">
          <option value="{{sorting.sortQuery}}" ng-repeat="sorting in phones.sorting"
                  ng-selected="sorting.sortQuery == orderProp"
                  ng-disabled="sorting.disabled">{{sorting.title}}</option>
      </select>

  </div>
  <div class="col-md-10">
    <!--Body content-->

    <ul class="phones">
      <li ng-repeat="phone in phones.data | filter:query | orderBy:orderProp">
        <span>{{phone.name}}</span>
        <p>{{phone.snippet}}</p>
        <p ng-if="phone.weight">Weight: {{phone.weight}}g</p>
        <p ng-if="phone.androidVersion">Android Version: {{phone.androidVersion}}g</p>
        <hr/>
      </li>
    </ul>

  </div>
</div>

On the other hand detailed configuration may appear to be excessive for a regular real-world site. As well as passing data that changes once or two in a lifetime with each request should be considered as an example of a bad practice. You can achieve this behaviour in a number of different ways, better ways, but the goal of this comment is to share my vision with you, hope it helps :)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.