javascript - Using $filter in Angular directive - Stack Overflow

I have built out an Angular directive to display a D3 visualization. I make use of $filter within the t

I have built out an Angular directive to display a D3 visualization. I make use of $filter within the tickFormat function on my y-axis like so:

ySalesAxis = d3.svg.axis()
  .orient('left')
  .ticks(6)
  .scale(ySalesScale)
  .tickFormat(function(d) {
    return $filter('formatSalesValue')(d.value, 'USD');
  });

The problem I'm seeing is that none of these tick labels appear when the page first loads. Indeed if I console.log($filter('formatSalesValue')(d.value, 'USD')) I get 6 undefined (since my ticks property is set to 6). However, as soon as I take an action, clicking within the brush filter for example, the tick labels appear properly formatted.

My formatSalesValue filter calls a service (async operation) because there are dozens of currencies cycling into and out of the system, details of which I retrieve from a DB. I am sure this is the reason my tick labels are undefined. What can I do to make sure these values appear right after page load? Note: I've attempted wrapping my tickFormat function in a call to scope.$apply but I get a digest already in progress error.

I have built out an Angular directive to display a D3 visualization. I make use of $filter within the tickFormat function on my y-axis like so:

ySalesAxis = d3.svg.axis()
  .orient('left')
  .ticks(6)
  .scale(ySalesScale)
  .tickFormat(function(d) {
    return $filter('formatSalesValue')(d.value, 'USD');
  });

The problem I'm seeing is that none of these tick labels appear when the page first loads. Indeed if I console.log($filter('formatSalesValue')(d.value, 'USD')) I get 6 undefined (since my ticks property is set to 6). However, as soon as I take an action, clicking within the brush filter for example, the tick labels appear properly formatted.

My formatSalesValue filter calls a service (async operation) because there are dozens of currencies cycling into and out of the system, details of which I retrieve from a DB. I am sure this is the reason my tick labels are undefined. What can I do to make sure these values appear right after page load? Note: I've attempted wrapping my tickFormat function in a call to scope.$apply but I get a digest already in progress error.

Share Improve this question edited Mar 2, 2016 at 20:46 MattDionis asked Feb 29, 2016 at 21:04 MattDionisMattDionis 3,62610 gold badges55 silver badges111 bronze badges 9
  • 1 Might be an issue with tickFormat being called outside of a digest cycle. – lintmouse Commented Feb 29, 2016 at 21:08
  • 2 If so, add scope.$apply() before your return statement - presuming you are in a directive and the linking function – JanS Commented Feb 29, 2016 at 21:09
  • 1 Create demo that replicates problem – charlietfl Commented Feb 29, 2016 at 21:26
  • See Replacing d3.js with pure SVG + AngularJS. – georgeawg Commented Feb 29, 2016 at 21:45
  • 1 Any way you could put this into a codepen or something? I just tried calling $filter from .tween() and everything seemed to work ok. Is the value d.value in the format that formatSalesValue is expecting? – cDecker32 Commented Mar 4, 2016 at 21:08
 |  Show 4 more ments

2 Answers 2

Reset to default 8 +50

Axis's tickFormat method runs passed callback and uses value returned by it in sync way. That's why you get undefined on the first call, as your $filter is async.

If this async call is only for performance reasons you should make it sync and look for improvements elsewhere. Should angular watch for so many independent changes it could clog with $digest cycles.

If you make JSBin I probably could tell you more.

TL;DR

Try using the Angular $timeout function.


Based on your question, the issue might be any number of things, but this is what I think is the problem:

Possible issue

It think that part of the problem is that the what you're getting is happening in a weird bit of the event loop.

$timeout is useful functions because it runs when the current stack is cleared and after n milliseconds have passed, if no time to delay is given, $timeout simply runs as soon as the stack unwinds. It's a useful trick for executing asynchronous code in a single thread.

Using $timeout with 0 delay doesn't actually mean the call back will fire-off after zero milliseconds. I just gets executed after a the queue of tasks is processed. Which is when you want to update your labels.

$timeout will actually triggers a digest when it's ready to do so.

Possible solution

$timeout(function() {
  // Update the label with what es back from the server
}, 0, false);

This is a good video explaining how the Javascript event loop works: What the heck is the event loop anyway?

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745471969a4629174.html

相关推荐

  • javascript - Using $filter in Angular directive - Stack Overflow

    I have built out an Angular directive to display a D3 visualization. I make use of $filter within the t

    2小时前
    30

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信