Taranjeet Singh
Taranjeet Singh

Reputation: 337

How to dynamically set ViewEncapsulation for a Web Component?

I am trying to initialise a component with or without Shadow DOM based on the browser (because IE does not support Shadow DOM).

I check whether it is IE11 and set the encapsulation to Emulated for IE and ShadowDom for other browsers.

const agent = window.navigator.userAgent;
const isIe11 = agent.indexOf('MSIE') === -1 && agent.indexOf('Trident') > 0;

@Component({
   selector: 'my-web-component',
   templateUrl: '...html',
   styleUrls: ['...scss'],
   encapsulation: isIe11 ? ViewEncapsulation.Emulated : ViewEncapsulation.ShadowDom
})
export class NavbarComponent implements OnInit { ... }

The value of isIe11 is correct as per the return value of browser check but the encapsulation always ends up being ViewEncapsulation.Emulated.

I confirmed this via the DOM inspector because I do not see #shadow-root in the DOM. Instead, I see _ngcontent-c0 which confirms the encapsulation is emulated.

Upvotes: 2

Views: 1105

Answers (1)

Poul Kruijt
Poul Kruijt

Reputation: 71891

This is not possible in the way you envision it, because angular compiles your code in AOT mode, and during the compilation step the browser is obviously not known.

I can only think of one way to achieve this. You have to compile the same application twice. Once for non ShadowDom compatible browser, and one in which this is possible.

Then on your server you serve whichever is needed based on the browser requesting it. I suppose you can also find a hacky way to do it inside the index.html which will load the correct angular libraries based on the current browser. This will require some after ng build script.

You can handle the encapsulation needed from within your environment file though, so if you have two different environments for compatible and non compatible browsers, you can add a property inside your environment:

// non shadow dom compatible env
export const environment = {
  // ...
  defaultEncapsulation: ViewEncapsulation.Emulated
}


// shadow dom compatible env
export const environment = {
  // ...
  defaultEncapsulation: ViewEncapsulation.ShadowDom
}

If you have those two environment files for your production builds, you can edit the bootstrapModule method inside your main.ts to read the value:

platformBrowserDynamic().bootstrapModule(AppModule, {
  defaultEncapsulation: environment.defaultEncapsulation
});

Upvotes: 3

Related Questions