Wednesday 7 October 2015

Tooltip styling is removed when used in ngRepeat

Problem: I have a tooltip that is styled using jQuery, but when it is used in an ngRepeat the styling is removed.

Examples:

Correct styling (no ngRepeat):




No styling (inside ngRepeat):






Process: I did a bit of research and it seemed like an ngRepeat scoping issue; where the ngRepeat was unable to access the correct styling as each repeat is the child of the repeater, not the parent and therefore loses some bindings.

I made a Stack Overflow post to try and see if anyone could confirm my theory and potentially provide a solution.

I created a new tooltip using css instead of jQuery to see if it was a scoping issue. After some fiddling around I got it working inside the repeater! However the width of the tooltip was very narrow:



















I created this Stack Overflow thread to ask others ideas on how to fix it after trying a bunch of fixes myself. The only response was someone suggesting changing the position value from absolute to relative:















It seems that more work would have to be done because not only did the positioning have to be redone, the tooltip was not dynamic in that it was being cut off on browser resizing. So I went back to solving the ngRepeat issue with the jQuery tooltip as this is something I wanted to solve and a better option than having redundant versions of tooltips.

Reasoning: I learnt that on the page load event the jQuery binds the custom tooltip class to tooltip function. However, when it's used in the repeater the event is fired after the page load and there is no existing binding. Therefore it is necessary to bind newly created elements to the tooltip again.

Basically the jQuery is initialised and rendered, but the ngRepeat is on the client side. Each repeat is dynamically generated with the scope of the child, not the parent, so all original bindings are out of scope and need to be re-binded after the ngRepeat has been created.

Solution: Re-bind all dynamic elements to the ngRepeat after it has been initialised and rendered. Referenced this post for a solution.

Create new directive to broadcast when the ngRepeat has finished rendering:
In the controller create a listener for the broadcast that then updates the parent of the tooltip (which in turn updates the tooltip):
Add on-finish-render="ngRepeatFinished" to the ngRepeat in the ascx:
Result:

No comments:

Post a Comment