0

Sorry if the title is not the most accurate.. So what I'm trying to do and what are my reasons behind it. I have a list of entries which can be pretty huge, up to 400 items, I get this list from ajax request, now if the first item has attribute running I want to extract it from the list(by using splice()) and pass it to a directive, which can work on it in an isolated scope. Why? Because the running entry will have a timer on it, which adds +1 to one of it's attributes each second with $timeout.

Now I want it to be isolated because of this Angular.js filters and functions on scope that is changing every second I don't want filters and everything on the list of not-running entries to be called every second just because something(timer especially) changed on the running entry.

Now when I press save or something, I want to put the running entry back to the entries, only with running: false now.

I kind of know how to inherit object from parent and create an isolated scope from it on the directive - http://plnkr.co/edit/zq3urVh5t6N12T5ZrViO?p=preview

Passing it there this way doesn't really seems ideal, but I was told it was fine and nothing really against best practice.

Now here comes the problems/question

  1. Is there any way to pass "running" the directive without adding it to the scope, because it's pretty much useless there once it gets copied
    • should I look for a way of passing it without adding it to the scope?
    • or should I deleted it after its copied?
    • or should I leave it because it doesn't matter?
  2. if ENTRIES are being set with ajax, it's impossible to copy the running one, because it's not yet set - http://plnkr.co/edit/vH3hKbkTkTvcHqykIXDt?p=preview

Thanks!

Community
  • 1
  • 1
fxck
  • 4,898
  • 8
  • 56
  • 94
  • if you want to pass variable from controller to directive you have to set attribute and use attribute inside the scope like scope:{entry:'@items'} for detailed explaination pls see http://docs.angularjs.org/guide/directive – Ajay Beniwal Apr 13 '13 at 09:23
  • @ is not going to work for objects, see http://plnkr.co/edit/evst1hkDcoCvvLb8610X?p=preview and I would still have to add the running entry to the scope to be able to pass it to the directive – fxck Apr 13 '13 at 09:32
  • its not true just use below code in html – Ajay Beniwal Apr 13 '13 at 09:52
  • how is it not true, you are passing it only a string with name in your example.. – fxck Apr 13 '13 at 09:59

2 Answers2

0

if you want to pass complete literal object that you have to use '=' but if you want to use @ then you have to make use of $eval see little example of working

<!doctype html>
<html ng-app="plunker" >
<head>
  <meta charset="utf-8">
  <title>AngularJS Plunker</title>

  <link rel="stylesheet" href="style.css">
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
  <script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
    <input ng-model="obj.name">

    <my-directive obj="obj" title="{{title}}">

      </my-directive>
    <script type="text/javascript">
        var app = angular.module('plunker', []);

        app.controller('MainCtrl', function ($scope) {
            $scope.obj = { name: "John", surname: "Doe" };
            $scope.title = { name: 'abc' };
        });


         app.directive('myDirective', function () {
        return {
            restrict: 'E',
            template: "<div><span>{{obj.name}}<span><span>{{title}}<span></div>",
            replace: true,
            scope: { title: '@', obj: '=' },
            link: function (scope, element, attrs) {
                attrs.$observe('title', function (value) {
                    alert(scope.$eval(value).name);
                })


            }
        }
    })
    </script>
</body>
</html>
Ajay Beniwal
  • 18,857
  • 9
  • 81
  • 99
  • I need far more than just the name though, entry will have at least 5 other attributes, that's why I want to pass it the whole entry object. – fxck Apr 13 '13 at 09:58
  • i thought you just want to pass one property for complete literal pls use = property – Ajay Beniwal Apr 13 '13 at 10:53
  • = would set up bi-directional binding, wouldn't it? Which is again no good for me, I *don't want* directive's scope to affect parent scope. Reasons are in the second paragraph of my question. – fxck Apr 13 '13 at 11:08
  • then you have to use scope.eval in the directives – Ajay Beniwal Apr 13 '13 at 11:16
  • one other way could be observing the attribute changes as edited above – Ajay Beniwal Apr 13 '13 at 14:00
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/28168/discussion-between-ajay-beni-and-foxx) – Ajay Beniwal Apr 13 '13 at 16:37
0

Change your directive to have scope: true - this is then isolated but inherits the parent

app.directive('myDirective', function($timeout) {
    return {
    restrict: 'E',
    scope: true,
        link: function(scope, element, attrs) {
            scope.timer = 0;
            $timeout(function tick() {
                scope.timer = scope.timer+1;
                $timeout(tick, 1000);
            });      
        }
    }
})

then in your directive just use it as if it was in the parent scope!

<my-directive>
  <h4>"running" entry on directive in isolated scope</h4>
  <p>Timer: {{timer}}</p>
  {{ running | json }}<br/>
  <input type="text" ng-model="running.name" />
</my-directive>

http://plnkr.co/edit/f5AzfjoEmRT9P1Dw8REj?p=preview

sidonaldson
  • 24,431
  • 10
  • 56
  • 61