Skip to content
This repository was archived by the owner on Oct 2, 2019. It is now read-only.

Avoid double-compilation of ui-select-choices directive. #170

Closed

Conversation

dlongley
Copy link

Notes:

  • Instead of replacing the ui-select-choices element using
    an angular template and then later transcluding content
    and recompiling the entire element at post-link time, do
    not provide a template but edit the template element in
    compile prior to linking. This approach allows the template
    to be fully constructed before the link phase and avoids
    any complications with double-linking the same element
    and/or issues with binding the transcluded contents to
    the wrong scope and introducing memory leaks.
  • This patch was started prior to a fix that avoided linking
    the transcluded content to the wrong scope (which was
    also producing memory leaks), but solves the problem
    in a different way -- namely preparing all of the content
    before compilation. This also eliminates any need for an
    additional helper directive.
  • This approach may help future-proof the uiSelectChoices
    directive as well -- as it was using "replace: true" which
    is deprecated in Angular. However, because the ui-select-choices
    element is no longer replaced, some changes had to be made to
    the CSS to account for its existence. These may need to be
    tweaked/simplified in the future -- the changes made were
    intended to be as non-intrusive/deviate as little as possible
    from any original intent.
  • A test was changed to look for different exception text as
    the element that is transcluded is found by element tag
    or attribute now, not by classname.

- Instead of replacing the ui-select-choices element using
  an angular template and then later transcluding content
  and recompiling the entire element at post-link time, do
  not provide a template but edit the template element in
  compile prior to linking. This approach allows the template
  to be fully constructed before the link phase and avoids
  any complications with double-linking the same element
  and/or issues with binding the transcluded contents to
  the wrong scope and introducing memory leaks.
- This patch was started prior to a fix that avoided linking
  the transcluded content to the wrong scope (which was
  also producing memory leaks), but solves the problem
  in a different way -- namely preparing all of the content
  before compilation. This also eliminates any need for an
  additional helper directive.
- This approach may help future-proof the uiSelectChoices
  directive as well -- as it was using "replace: true" which
  is deprecated in Angular. However, because the ui-select-choices
  element is no longer replaced, some changes had to be made to
  the CSS to account for its existence. These may need to be
  tweaked/simplified in the future -- the changes made were
  intended to be as non-intrusive/deviate as little as possible
  from any original intent.
- A test was changed to look for different exception text as
  the element that is transcluded is found by element tag
  or attribute now, not by classname.
@dlongley
Copy link
Author

This PR takes a different approach to implementing the uiSelectChoices directive. It was started because the ui-select widget was leaking memory in our applications due to some bad/double linking of transcluded elements. That has since been changed, however, this PR attempted to rethink the way the directive was implemented by ensuring that its template was fully-prepared prior to linking. The current implementation performs transclusion after the element has been compiled -- but the transcluded elements are meant to be in the same scope as an ng-repeat ... which requires a recompilation of the entire directive post-link.

This PR, instead, manually loads the directive's template from the template cache and prepares the ng-repeat during compilation so that everything is ready to go at link time. While this approach requires a little more upfront work, it also eliminates the need for an additional helper directive to deal with transclusion issues and, IMO, properly sets up the element prior to linking. I think it's a little odd to recompile the entire directive post-link, but given some of the limitations/clunkiness of Angular in this particular use case it was understandable.

What Angular really needs for use cases such as these is better access to transcluded elements during compilation time -- where you don't care about the scope (compile-time transclusion access is actually deprecated for the very reason that there's no scope access). In these cases you just want to make the public-facing API for your directives a bit nicer for users -- and you want to, for instance, build your own ng-repeat templates from user input before they are linked. The alternative is to make the user write the ng-repeat themselves and your API for using the directive becomes more verbose and potentially brittle, but I suppose there are arguments for not hiding any ng-repeat details from the user as well.

@wesleycho
Copy link
Contributor

Going to close this as too old - feel free to open a new PR with changes against current master.

@wesleycho wesleycho closed this Mar 27, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants