0

I'm trying to build a simple web app that displays tables of items grouped by category. I want the categories to be collapsible, the tables to be sortable, and I want the data to update every 60 seconds without reloading the whole page (the data comes from my_json_data.php which queries a DB and outputs the results as json). It seems like Angular.js is the preferred way to do this (particularly the last part). I'm totally new to this but I've got the basic functionality working, but I'm running into an issue. When the table data refreshes it resets the collapse and sorting, which I don't want to happen. Here's the basic outline of everything:

index.html:

<body ng-app="myApp">

<div ng-controller="myController">
  <div ng-repeat="category in categories" class="panel panel-primary">

    <!-- Collapsible category panel -->
    <div class="panel-heading">
      <h5 class="panel-title" ng-click="show = !show">
        {{ category.name }}
      </h5>
    </div>

    <!-- Sortable table of items -->
    <div class="table-responsive" ng-hide="show">
      <table class="table table-condensed table-striped">
        <thead>
          <th ng-click="sortType = 'name'; sortReverse = !sortReverse">Name</th>
          <th ng-click="sortType = 'size'; sortReverse = !sortReverse">Size</th>
          <th ng-click="sortType = 'price'; sortReverse = !sortReverse">Price</th>
        </thead>

        <tbody>
          <tr ng-repeat="item in category.items | orderBy:sortType:sortReverse">
            <td>{{ item.name }}</td>
            <td>{{ item.size }}</td>
            <td>{{ item.price }}</td>
          </tr>
        </tbody>
      </table>
    </div>

  </div>
</div>

</body>

Factory:

app.factory('myFactory', ['$http', function($http) {

  var myFactory = {};

  myFactory.getData = function () {
          return $http.get('my_json_data.php');
  };

  return myFactory;

}]);

Controller:

app.controller('myController', ['$scope', '$interval', 'myFactory', function ($scope, $interval, myFactory) {

    $scope.categories;

    getData();

    function getData() {
        myFactory.getData()
            .success(function (data) {
                $scope.categories = data;
            })
            .error(function (error) {
                $scope.status = 'Unable to load data: ' + error.message;
            });
        $interval(getData, 60000);
    };

    $scope.sortType     = 'price'; // set the default sort type
    $scope.sortReverse  = true;  // set the default sort order
}]);

So everything works exactly how I'd like it to, except every 60 seconds when the data is refreshed, it reopens any category divs that have been closed, and it re-sorts the tables to the default order. Hopefully there's a relatively simple fix, but I'm open to rebuilding everything from the ground up if I've made some glaring rookie mistakes. Thanks!

2
  • Can you please add the json that your php script is returning? So it's easier to create a demo jsfiddle. Commented Jun 24, 2015 at 20:17
  • Sorry for the delay, just seeing this now and it seems you've answered my question already. Thanks! Commented Jun 25, 2015 at 2:43

1 Answer 1

1

I think your ng-repeat sorting is changing on reload of your data because the $$hashkey is overidden with $scope.categories = data;

If you are cloning the previous categories and extend the new one with existing hashkey the order is not affected.

Not sure if this is working with your data but it's working in the demo.

You have had a bug inside your getData method. Don't use $interval because it will create many parallel intervals. You need here the $timeout service.

In the demo I've set the time to 10sec, so you don't have to wait one minute for the reload.

Please have a look at the demo below or this jsfiddle.

var app = angular.module('myApp', []);

app.factory('myFactory', ['$http', function($http) {

  var myFactory = {};

  myFactory.getData = function () {
          return $http.get('http://crossorigin.me/http://www.mocky.io/v2/558b11f45f3dcb421106715d');//'my_json_data.php');
  };

  return myFactory;

}]);

app.controller('myController', ['$scope', '$timeout', 'myFactory', function ($scope, $timeout, myFactory) {

    $scope.categories;

    getData();

    function getData() {
        var clonedCat;
        myFactory.getData()
            .success(function (data) {
                console.log(data);
                clonedCat = angular.copy($scope.categories|| {});
                $scope.categories = angular.extend(clonedCat, data);
            })
            .error(function (error) {
                $scope.status = 'Unable to load data: ' + error.message;
            });
        $timeout(getData, 10000); //don't use interval here because it always creates new intervals
    };
    console.log('controller exec.');
    $scope.sortType     = 'price'; // set the default sort type
    $scope.sortReverse  = true;  // set the default sort order
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">

<div ng-controller="myController">
  <div ng-repeat="category in categories" class="panel panel-primary">

    <!-- Collapsible category panel -->
    <div class="panel-heading">
      <h5 class="panel-title" ng-click="show = !show">
        {{ category.name }}
      </h5>
    </div>

    <!-- Sortable table of items -->
    <div class="table-responsive" ng-hide="show">
      <table class="table table-condensed table-striped">
        <thead>
          <th ng-click="sortType = 'name'; sortReverse = !sortReverse">Name</th>
          <th ng-click="sortType = 'size'; sortReverse = !sortReverse">Size</th>
          <th ng-click="sortType = 'price'; sortReverse = !sortReverse">Price</th>
        </thead>

        <tbody>
          <tr ng-repeat="item in category.items | orderBy:sortType:sortReverse">
            <td>{{ item.name }}</td>
            <td>{{ item.size }}</td>
            <td>{{ item.price }}</td>
          </tr>
        </tbody>
      </table>
    </div>

  </div>
    {{categories|json}}
</div>

</div>

Sign up to request clarification or add additional context in comments.

1 Comment

This worked brilliantly, thank you so much for taking the time to work this out and explain it to me!

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.