2

I am upgrading an existing Angular 2 app that makes extensive use of JQuery Plugins, D3, and even some React Components (All of which use sizzle so I am pretty sure it applies to all). Since it really doesn't make sense to rewrite all of these at once I am trying to wrap some of them in an Angular 2 Component. To show you what I mean I have a simple component that uses Jquery to add an item to the DOM...

import { Component, AfterViewInit, ElementRef } from '@angular/core';
declare var $:JQueryStatic;
@Component({
  selector: 'px-spinner',
  template: String(require('./spinner.template')),
  styles: [require('!raw!stylus-loader!./spinner.styles')]
})
export class SpinnerComponent implements AfterViewInit{
  constructor(public el:ElementRef){}
  ngAfterViewInit(){
    $(this.el.nativeElement).append("<div class='output'>Output 2</div>")
  }
}

The problem here is the styles are not applied to output 2. When I look at the DOM the reason becomes apparent...

<ng-spinner class="ng-scope" id="NG2_UPGRADE_0_pxSpinner_c0" _nghost-ylc-1="">
  <div _ngcontent-ylc-1="" class="start">
    <div _ngcontent-ylc-1="" class="output">output 1</div>
  </div>
  <div class="output">Output 2</div>
</ng-spinner>

The DOM Element added by JQuery is missing the _ngcontent-ylc-1="". Is there a way to have Ng2 add this when JQuery injects the DOM?

Update

The question is similar to this one (Angular2 - adding [_ngcontent-mav-x] to styles) but I guess the question is how do I include the injected dom in the ViewEncapsulation?

Community
  • 1
  • 1
Jackie
  • 21,969
  • 32
  • 147
  • 289

2 Answers2

1

If you use a style like

:host .output {
  ... 
}

it should be applied.

If this doesn't work use

:host /deep/ .output {
  ... 
}
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • This would just make it global correct? I want to keep the ViewEncapsulation – Jackie Oct 10 '16 at 15:27
  • Updated to reflect that I still want it isolated to DOM that is encapsulated in the component. – Jackie Oct 10 '16 at 15:30
  • 1
    You can't include the inected DOM in ViewEncapsulation. The emulation is calculated either at build time (with AOT) or when the component was created. What might work though is to read the `_ngcontent-ylc-1` property from the components host element and apply it to your injected HTML as well. `/deep/` doesn't make styles global but the selector is rewritten so that the components children are addressed as well. – Günter Zöchbauer Oct 10 '16 at 15:30
  • 1
    Thanks for clarifying Gunter I will try that out and get back to you! – Jackie Oct 10 '16 at 15:31
  • Also do I need the `:host` what is that doing? – Jackie Oct 10 '16 at 15:31
  • 1
    Host is a selector that matches the current element. With `:host xxx` or `:host /deep/ xxx` all descendants elements that match `xxx` are addressed. – Günter Zöchbauer Oct 10 '16 at 15:32
  • One question, does this work on older browsers that do not support shadow DOM? I haven't had time to try on IE10 – Jackie Oct 11 '16 at 14:24
  • Yes, `/deep/` and `>>>` are only processed by Angular2 and rewritten to styles that don't use these combinators. This is also why `/deep/` and `>>>` only work with `ViewEncapsulation.Emulated` (default). – Günter Zöchbauer Oct 11 '16 at 14:29
1

I think you can get the _ngcontent-ylc-1 property in ngAfterViewInit from nativeElement. And then apply this property to your appended html.

peng37
  • 4,480
  • 1
  • 11
  • 13