1

I'm looking for advice. My following code doesn't work, most likely because of the directive or the filter that don't get updated when the $scope.clients object changes:

$scope.clients = {
    "IDa": {"position": {index: 1}, "name": "a"},
    "IDb": {"position": {index: 2}, "name": "b"},
    "IDc": {"position": {index: 3}, "name": 'c'},
    "IDd": {"position": {index: 4}, "name": "d"},
    "IDe": {"position": {index: 5}, "name": "e"},
    "IDf": {"position": {index: 6}, "name": "f"},
    "IDg": {"position": {index: 7}, "name": "g"},
    "IDh": {"position": {index: 8}, "name": "h"},
    "IDi": {"position": {index: 9}, "name": "i"}
};

I need to display 7 items (divs) based on the position property. The tricky thing is that if there are less than 7 items in the object, the view must still have 7 items just instead of the name property it'll say 'Waiting for client'. The view must display those 7 items in the order of the position 1..7.

The HTML:

<div class="streams__unit" stream client="clients | position:1">
       {{ client.name || 'Waiting for client' }}
</div>
<div class="streams__unit" stream client="clients | position:2">
       {{ client.name || 'Waiting for client' }}
</div>
<div class="streams__unit" stream client="clients | position:3">
       {{ client.name || 'Waiting for client' }}
</div>
<div class="streams__unit" stream client="clients | position:4">
       {{ client.name || 'Waiting for client' }}
</div>
<div class="streams__unit" stream client="clients | position:5">
       {{ client.name || 'Waiting for client' }}
</div>
<div class="streams__unit" stream client="clients | position:6">
       {{ client.name || 'Waiting for client' }}
</div>
<div class="streams__unit" stream client="clients | position:7">
       {{ client.name || 'Waiting for client' }}
</div>

Here's the position filter:

angular.module('app').filter('position', function () {
    return function (clients, index) {
        var client = {};

        for(var i in clients) {
            if(clients[i].position.index === index) {
                client = value;
                break;
            }
        };

        return client;
    }
});

But it doesn't work since the clients object is updated later than the filter fires (i think). Here's the directive:

angular.module('app').directive('stream', function () {
    return {
        restrict: 'EA',
        controller: function($scope) {
            $scope.$watch('client', function(val) {
                console.log('watch worked', val);
            });
        },
        scope: {},
        link: function (scope, element, attrs, fn) {
            scope.$watch(attrs.client, function(client) {
                scope.client = client;
            });
        }
    };
});
2
  • Can you be a little more clear on what you are trying to achieve? maybe a working example? Also, could this be achieved with a ng-repeat and a limitTo filter and a orderBy filter? Commented Jun 30, 2015 at 0:15
  • I'm afraid ng-repeat wouldn't work since the view MUST have 7 items in place. And it's object may have 0 or less than 7 items. Commented Jun 30, 2015 at 0:29

1 Answer 1

1

One approach is a 2 step approach:

  1. preprocess the object into the desirable array.
  2. use ng-repeat with 'orderBy' filter and 'limitTo' filters applied.

Here's a plunker example: http://plnkr.co/edit/AYEvW9DmxdZEF9lVSD20?p=preview

HTML:

<div ng-repeat="item in clientsArr | orderBy: 'position.index' | limitTo: 7" class="streams__unit">
   {{ item.name || 'Waiting for client' }}
</div>

JavaScript:

angular.module('app', []).controller('ExampleCtrl', function($scope) {

$scope.clients = {
  "IDa": {"position": {index: 1}, "name": "a"},
  "IDb": {"position": {index: 2}, "name": "b"},
  "IDc": {"position": {index: 3}, "name": 'c'},
  "IDd": {"position": {index: 4}, "name": "d"},
  "IDe": {"position": {index: 5}, "name": "e"}
};

$scope.clientsArr = [];
for(var i in $scope.clients) {
  $scope.clientsArr.push({
      id: i,
      position: $scope.clients[i].position,
      name: $scope.clients[i].name
    });
  }

  while($scope.clientsArr.length < 7) {
    $scope.clientsArr.push({});
  }
});
Sign up to request clarification or add additional context in comments.

2 Comments

I also need to watch for changes on the clients object, because some items can switch places (position.index changes), dynamically appear, dissapear, change property values and so on.
Also lets say I have items with indexes 1,2,4. I still need to have an empty item in position 3. And this code won't work in that case because it doesn't put the element in the right position.

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.