How to enable/disable a directive dynamicaly from "outside", while still keeping the transcluded content

22 views
Skip to first unread message

Brian

unread,
Apr 24, 2015, 9:54:12 AM4/24/15
to ang...@googlegroups.com
Hi,

I am trying to find out how to enable and disable directives on the fly, and recompiled based on the original DOM, controlled by an outer directive if this is possible, or controlled by anything else if its not. :)

Static page input 
<div data-rootDirective="XYZ"...
   blabablalb
</div

Based on XYZ, the root directive, will wrap the transcluded DOM in certain "additional functionality"  by way of more directives,
output
<div class="rootDirective...
  <div class="directive1" ...
    <div class="directive2" ...
...
blablabla
</div>
Then the element is $compiled

This part is working great, but now I need to be able to dynamicaly enable/disable all the wrapping directives.
Then it gets tricky though, because the DOM should be recompiled based on the static/original content, not the output of the various directives that were previously compiled.


I am playing around a bit with linking/transclude functions right now, trying to get something working, but so far everything is a bit murky.

Anyone have a clean solution that keeps the logic isolated either to its own unit, or to the rootDirective only?

Thanks,
Brian

Sander Elias

unread,
Apr 24, 2015, 10:12:03 AM4/24/15
to ang...@googlegroups.com
Hi Brian,

Do i understand it correctly that you have an outside event, that when triggered, needs to replace your angular app with it's orginal HTML content? (that later on might be reenabled?)

Regards
Sander

Brian

unread,
Apr 24, 2015, 11:11:24 AM4/24/15
to ang...@googlegroups.com
Yes - outside event
No - Not exactly replace with original content

I need to be able to individual toggle each "inner" directive. Basicaly I have sets of directives with a on/off for each one.

So lets say I have 3 directives in the set
Directive A2B that replaces elements <a... with <b...
Directive B2C that replaces elements <b... with <c...
Directive A2D that replaces elements <a... with <d...
and I have the directive priorities, such that:

static page
<div data-root-directive>
 <a...
</div>


root directive wraps it only in the enabled directives and compiles with transcludes and stuff
<div data-root-directive>
 
<div data-a2b>
 
<div data-b2c>
   
<div data-a2d>
    <a...
   
</div>
 
</div>
 
</div>
</div>

after compiling we are left with the DOM (note A2D never executes because of the directive priority)
<div data-root-directive>
 
<div data-a2b>
 
<div data-b2c>
   
<div data-b2c>
    <c...
   
</div>
 
</div>
 
</div>
</div>

Now, dynamically I want to say, ok, I want to disable A2B and enable A2D

So there's 2 problems at this point.
The first is that the dom is now changed to <c... but it should all be recompiled based on the original <a...
The second is the mechanics of how to actualy do the enable/disable

I am trying to avoid a lot of manual jquery, and stick with angular only if I can, but ill do whatever works....


Sorry for the huge response, I hope its not confusing.

Brian

unread,
Apr 24, 2015, 11:13:10 AM4/24/15
to ang...@googlegroups.com
typo in 3rd code block
 <div data-a2b>
  
<div data-b2c>
   
<div data-a2d> <---

Sander Elias

unread,
Apr 24, 2015, 12:28:27 PM4/24/15
to ang...@googlegroups.com
Brian,

Ok, I see what you are trying to do. I'm not sure if this is a good idea to begin with. Let me first state that it is possible, with plain JS and some angular. No jQuery needed at all.
There are a couple of things that needs to be done. 
  1. create an toggle directive that you add to each one you want to toggle. 
  2. run that at a higher priority, and make it terminate.
  3. when terminated, save the innerHTML to a temp storage.
  4. check if the direcive is enabled, if so compile what you have
  5. if not, take out the direcive, and then compile.
  6. rinse and repeat.
Be aware that this will involve lots of edge-cases and pitfalls. There is no simple solution, and the nesting of the directives doesn't make it simpler.
I'm pretty sure, that your use-case is solvable in a couple of other ways that are less error-prone and don't for starterts, a couple of ngIfs in your template will come a long way.

Regards
Sander

Brian

unread,
Apr 24, 2015, 12:55:40 PM4/24/15
to ang...@googlegroups.com
Ah I see what you're saying. It might get messy, agreed.
I think I was able to achieve what you're saying but without the toggle.

I failed to mention this earlier but I have a UID for each of these rootDirective elements, so I can store the precompiled version exactly per unique (rootDirective) dom element.
I changed my root directive's dom "wrapping" algorithm to wrap only the enabled directives
Then I trigger the recompile externaly and pass the cached precompiled content, which re-fired the root directive on the original content and wraps it in the NEW set of enabled directives.

Still in early testing, but it looks like it will be working...
Will post results when done

Brian

unread,
Apr 25, 2015, 1:31:11 AM4/25/15
to ang...@googlegroups.com
I got it working eventually, as I mentioned above. It took me forever to debug a problem with caching the precompiled dom by storing the result of the transclude function. It is some kind of jquery wrapper and refuses to behave the way I expect.
In the end I had to store it as angular.element("<div/>").append(clone).html()

Thanks Sander!

Sander Elias

unread,
Apr 25, 2015, 3:43:50 AM4/25/15
to ang...@googlegroups.com
Hi Brian,

In the end I had to store it as angular.element("<div/>").append(clone).html()
Believe it or not, this makes sense. (at least to me ;) )
This has to do with the way angular hooks up to the DOM. If you want we can goo deeply into details here.

I'm glad you got it sorted out.
Regards
Sander
Reply all
Reply to author
Forward
0 new messages