We didn't need a perfectly clean solution, just one that showed we could get the performance we desired while still following Angular's main tenets -- separate model from view, leave HTML generation to templates, testability, etc. We were able to show to ourselves that we could leave all the HTML generation and updating to directives similar to ng-repeat, with just a few small optimizations. In the end, the only way we bent the abstraction layer was to rely on a non-public variable to enable us to swap in and out watchers quickly. It's a small dependency and one that could be removed through a small change to Angular's API or some other tricks folks have suggested in other comments here.