0

I'm slowly getting the hang of AngularJS - but struggling!

I have got some working directives for figures drawn using d3.js. I am trying to implement a "pop-out in a fullscreen modal / lightbox" feature, using ui.bootstrap.modal.

To draw the figures, the directive functions need to know the width and height of the final element, which I have taken from the width and height from the directive's parent element (as the directive element itself seems to not have dimensions as expected), e.g.

<figure id="parent"> <!-- parent has a defined width & height -->
    <figure2></figure2> <!-- my directive -->
    <figcaption>Caption goes here!</figcaption>
</figure>

But of course, when it's in a modal, the directive's parent element doesn't have a width & height until it's open and visible, after the directive's link function gets fired.

I've tried to put a $watch on the parent element's width and height (based on this suggestion), but it's not working for me - I guess the link function is only fired once. (NB: My knowledge of how watch functions work is limited to this post - but I think this is where the solution might lie!)

Or should I be doing something based on the modal's opened or rendered promises? If so, where? It can't be in the directive (as the directive also exists outside the modal).

What is the best way to do this? Here's two Plunkers:

(NB: Figure 1 doesn't need the width / height, but Figure 2 does)

Thanks in advance!

Bonus questions (to save me coming back later!):

  • Is there an easy way to re-draw the figures on a window-resize event?
  • Is there an easy way to have a single figure-modal.html template which dynamically populates itself with the correct directive (<figure1></figure1> or <figure2></figure2>) based on a provided variable / expression?
Community
  • 1
  • 1
StevieP
  • 401
  • 3
  • 16

1 Answers1

0

Having gone back to this problem after some time away (learning how to do Angular!), I have found a solution loosely based on another answer (which I have since lost).

The trick is to set up two watches:

scope.$watch (function () {
  if (element.width() !== scope.dims.width || element.height() !== scope.dims.height) {
    scope.dims = {'width': element.width(), 'height': element.height()};
  }
});

scope.$watch ('dims', function (newVal, oldVal) {
  if (newVal === oldVal) return;
  alert('dimensions changed');
  draw();  // Call to function to redraw the graph
});

The first $watch updates the scope.dims object on each digest cycle. The second $watch fires when it is updated.

May not be the best code, but it works!

For future readers - let me know if you need to see a working Plunkr.

StevieP
  • 401
  • 3
  • 16