0

I would like to implement an Angular 2 directive that behaves like jQuery's wrapInner method.
The library I'm writing will use angular 2+ only (no jQuery).

Basically, the directive will take the content of the element or component it has been applied to, and wrap that content in a div (or perhaps wrap it in some other html tag that's passed in as a parameter)

For example,

<myComponent wrapInner>
   ... All The Content ...
</myComponent>  

should result in something like,

<myComponent >
   <div class="innerStyles" >
      ... All The Content ...
   </div>
</myComponent>  

I am not sure what the most angular-style 'idiomatic' approach to this, as it seems to involves manipulating the DOM which is discouraged.

So could this perhaps be something that is better off being a Structural directive? Or involve manipulating templates or using ViewContainer in some way? I dont know how to use those.

However, I have put together a plunker where I use the (discouraged) insecure and inefficient way of going about this; by manipulating DOM through ElementRef.

https://plnkr.co/edit/PyVyzv3KUQ8IcsdNnVt0

Kindly Assist.
I really appreciate it!

Somo S.
  • 3,997
  • 4
  • 26
  • 33
  • Just ignore that `ElementRef` is insecure. It's not more insecure that using jQuery. " do not automatically protect you from security vulnerabilities" means that you are not automatically secured by Angular. If you take care that you are not doing things that cause security issues yourself, it's perfectly secure. – Günter Zöchbauer Jan 21 '17 at 16:48
  • It's not just security that's a problem... in my plunker I found I had to manually loop through and add every child, grand child, great-grand-child .. node of every kind.. if their several layers of nested nodes this will become efficiency nightmare I imagine – Somo S. Jan 21 '17 at 16:58
  • There is nothing Angular2 provides. You can search if there are some JS approaches that make it easier. – Günter Zöchbauer Jan 21 '17 at 17:05

2 Answers2

0

I don't think there is a way to do it without direct DOM manipulation.

To make this work you would need a component and use it like

<myComponent wrapInner>
  <wrap-inner>
   ... All The Content ...
  </wrapInnter>
</myComponent>  

but there is no way to get rid of <wrap-inner> around the wrapper part (<div class="innerStyles" >)

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Thanks for quick feedback Günter . wrapInner can to only be a single directive (potentially a structural one).. if I could use components then I'd just use ng-content and that'd be pretty simple ... What I am trying to do is essentially emulate the ng-content functionality in a directive – Somo S. Jan 21 '17 at 17:04
  • If you want to use a directive, you are stuck with the approach you're already using. – Günter Zöchbauer Jan 21 '17 at 17:06
  • Hmm.. well that's surprising. I am thinking along the lines of that if Component decorator inherits Directive decorator, And Component somehow has the ng-content feature (even though that's not itself a directive) then it should, in worst case scenario, be possible to essentially write your own ng-content type thing that works exclusive with directives ... Since well one was written for component directives .. does that make sense? – Somo S. Jan 21 '17 at 17:13
  • I somehow doubt the ng-content source uses this sort of bruteforce thing in my plunker – Somo S. Jan 21 '17 at 17:16
  • A component has a view, a directive doesn't. I don't know how `` is implemented. It might be easier if you pass the content as `` then you can use ` – Günter Zöchbauer Jan 21 '17 at 17:22
  • Yes I stumbled on ViewContainerRef` while exploring if I could make this work as a structural directive.. Desugaring structural directive seems to wrap ` – Somo S. Jan 21 '17 at 17:40
  • Also `Renderer.createTemplateAnchor()` seems to dynamically be able to create a template .. is this the type of template you are referring to that I might need? – Somo S. Jan 21 '17 at 17:41
  • If you make it a structural directive, then ` ... All The Content ... ` becomes ` – Günter Zöchbauer Jan 21 '17 at 17:42
  • Hard to tell what `Renderer.createTemplateAnchor()` does from this huge amount of documentation it provides ;-). If you get an instance of `TemplateRef`, then it should work. – Günter Zöchbauer Jan 21 '17 at 17:44
  • Well this "vast" amount of documentation is exactly why i've taken to stack, I dont know who else to ask .. haha... hopefully someone who has experimented more in these unchartered areas will see this quesiton! – Somo S. Jan 21 '17 at 17:49
  • Maybe I put in a feature request for syntactic sugar device that places the template *inside* the host rather than outside .. haha – Somo S. Jan 21 '17 at 17:50
  • Unlikely that will happen :D, but it would be nice to get the content of a component as `TemplateRef` without explicitly wrapping it with a ` – Günter Zöchbauer Jan 21 '17 at 17:52
  • Yes, that would be great too! hmm.. i dont want to force my users to explicitly have to – Somo S. Jan 21 '17 at 17:54
  • You could use a structural directive on the content. That's a bit less pain, but not much. – Günter Zöchbauer Jan 21 '17 at 18:00
  • wrapping `ng-container` around the content first.. ? – Somo S. Jan 21 '17 at 18:02
  • 1
    Not sure what you mean? I mean `
    ... All The Content ...
    `. The `
    ` can be any other element that is the outermost element of "All The Content".
    – Günter Zöchbauer Jan 21 '17 at 18:05
  • by the way just so you know, the reason I am insisting on using directive instead of component for `[wrapInner]` is because if I wrote it as a compoenent (even with the same attribut selector) I wouldn't be able to apply it to other components (e.g. as I have done in the example on plunker).. I could only apply it to naitive html elements.. Whereas I can apply directive to components and elements.. Am I misunderstanding how that works? is there some way to apply a component to another component.?? – Somo S. Jan 21 '17 at 18:06
  • oh! what I meant was ` ... All The Content ... ` – Somo S. Jan 21 '17 at 18:09
  • That's right, you can't apply a component to another component. My suggestion was because you either need a component or a template element to have a way to place the content somewhere. Is there a reason you apply it to a component? The `wrapInner` attribute would need to be added by the user anyway. Why not adding it to the content instead as mentioned in my last comment? – Günter Zöchbauer Jan 21 '17 at 18:09
  • You can use `` or ` – Günter Zöchbauer Jan 21 '17 at 18:11
  • 1
    Oh I didn't know you can only have one sDirective per element.. thanks.. I'll think about your idea wrapping the div inside and putting a structural directive there... – Somo S. Jan 21 '17 at 18:17
  • http://stackoverflow.com/questions/34657821/ngif-and-ngfor-on-same-element-causing-error – Günter Zöchbauer Jan 21 '17 at 18:18
0

Not possible at the moment. But the Angular team has this feature on backlog.

You can follow progress at https://github.com/angular/angular/issues/8785

Somo S.
  • 3,997
  • 4
  • 26
  • 33