function called multiple times from template

In my template I have something like this:

{{formatMyDate(date)}}

but date is a scope variable that is not immediately available so this expression will call the function formatMyDate() many times (returning undefined) before returning the correct value.

I could check if the date is not null within the function but I guess it would be more clean NOT to call the function at all if the date is null.

Any way to achieve this? Would a custom filter help me out here?

<strong>EDIT:</strong> It was suggested that this behaviour could be normal, depending on the $digest cycle. I've then put a scope.$watch to verify how many times the value of date is changing. Note that I'm defining these in a directive.

scope.$watch('date', function(value){ console.log('watched_date: ' + value) })

and I've introduced a console.log() on my formatMyDate function as well

scope.formatMyDate = function(date){ console.log("called_date: " + date) return dateService.format(date, 'YYYY-MM-DD') }

Inspecting the console I get (pseudo code)

called_date: undefined watched_date: undefined called_date: undefined // many many times (around 20/30) called_date: correctValue //2 or 3 times watched_date: correctValue called_date: correctValue //other 3/4 times

I'm wondering if this is still due to the $digest cycle or it is a bug in my code

Answer1:

I would recommend you to do things differently:

Either use the date $filter or if you are doing something VERY unique and the date $filter is not good enough for you, then you could create your own $filter, like this:

app.filter('formatMyDate', function () { return function (date) { if (!date) return ""; var result; //your code here return result; }; });

And use it like this in your template:

{{date | formatMyDate}}

UPDATE:

I guess that I didn't quite answer your question, I just gave you advice on how to improve your code. This time I will try to answer your question:

The $digest cycle is the stage in which Angular ensures the changes of the model have settled, so that it can render the view with the updated changes. In order to do that, Angular starts a loop in which each iteration evaluates all the template expressions of the view, as well as the $watcher functions of the $scope. If in the current iteration the result is the same as the previous one, then Angular will exit the loop. Otherwise, it will try again. If after 10 attempts things haven't settled, Angular will exit with an error: The "Infite $digest Loop Error" (infdig).

That's why the first time that the $digest cycle runs all the expressions are evaluated (at least) twice. And then Every time that you make a change to the $scope or that one of the $watchers of the $scope gets triggered, the $digest cycle will run again in order to make sure that things have settled, so your expressions will be evaluated again. This is how Angular makes "data-binding" happen, it's a normal behaviour.

So in your case, when in your template you do this: {{formatMyDate(date)}} or this {{date | formatMyDate}} you're defining Angular expressions that will be evaluated every time that the $digest cycle runs, which as you can imagine is very often. That's why is very important to make sure that the $filters (or functions) that you use in your view are efficient and stateless.

Answer2:

You can do this:

{{date && formatMyDate(date)}}

will only execute the second case if the first condition exists and is different from null and undefined.

Check this fiddle: http://jsfiddle.net/HB7LU/7512/

人吐槽 人点赞

Recommend

Comment

用户名: 密码:
验证码: 匿名发表

你可以使用这些语言

查看评论:function called multiple times from template