How to have a component without inherited css in Angular 6 - css

I have a project that uses Angular 6 and Bootstrap, and now, i need to create only one page that can be responsive for use in mobile devices. So, i need to create this page/component without any css inherited from the project. How can I do this? Once I create the page, it already have some tags like and css classes that I just dont know where are them imported to this component

An option would be setting the viewEncapsulation to ShadowDom
#Component({
selector: 'app-test-comp',
templateUrl: './test-comp.component.html',
styleUrls: ['./test-comp.component.css'],
encapsulation: ViewEncapsulation.ShadowDom
})
export class TestCompComponent {}
But beware of the browser support. More about this:
https://angular.io/guide/view-encapsulation
https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM
and here you can find a polyfill if you need to support IE 11: https://github.com/webcomponents/polyfills/tree/master/packages/webcomponentsjs
https://caniuse.com/?search=shadow%20dom

Related

Prevent CSS overwrites from web components in parent page

I created a web component using Angular Elements (6.0.3). When I use the web component in another website, the webcomponent overwrites the styles of the parent page since it also uses Bootstrap. I know that there is the view encapsulation principle, but as far as I know the "Native" encapsulation is not yet fully supported. So for now I am using the default "Emulated".
I found out that if I add :host ::ng-deep in front of my styles, they are only applied to the web component itself which is great. However, all css and scss files that I load in angular.json seem to be overwriting the parent page too. Is there any way I can prevent this behaviour from imported style-files?
My style-imports in angular.json:
"styles": [
"node_modules/intl-tel-input/build/css/intlTelInput.css",
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"node_modules/angular-calendar/css/angular-calendar.css",
"src/styles.scss",
"node_modules/font-awesome/css/font-awesome.min.css",
"src/assets/css/wizard.css",
"src/assets/css/calendar.css",
"src/assets/css/ng2-select.css"
]
The 'styles' imports in the angular.json are for styles you wish to define globally to the whole app. To use ViewEncapsulation you'll need to link their stylesheets inside of their components like so:
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css'],
})

CSS classes not picked up during Angular 5 compilation

I'm using ag-grid in my angular 5 project. I'm trying to add css classes to the cells. Having looked the extensive documentation on ag-grid cell style I have tried to use cellClass and cellClassRules.
The styles are defined in the scss file, as an example:
.readonly-cell{ background-color: #cccccc; }
The scss file is then included in the component:
#Component({
selector: 'app-volume',
templateUrl: './volume.component.html',
styleUrls: ['./volume.component.scss']
})
I then apply the class to the column:
{headerName:'Power', field:'power', width:150, cellClass:'readonly-cell'}
The grid itself is working fine. The issue is that the the power cells do not change colour. When I check the rendered HTML in Firefox, I can see that the cell have indeed have the class readonly-cell applied to them. But the style details are not listed on the rules panel.
This makes me think that the classes are not being picked up during the compilation. I don't think it's an issue with ag-grid, but the way the style classes are being picked up.
Is there any way to troubleshoot why the classes and the definitions are not being included in the compilation?
You get that behavior because element you are trying to target by a CSS rule is generated outside your Angular component and Angular adds special attributes so that component CSS applies only to that component (and not to its child components, any DOM nodes added outside Angular etc.). You should either build all the HTML you need to style using Angular and in exactly the same component as your styles, or disable that feature. You can disable it either by using ViewEncapsulation.None:
#Component({
selector: 'app-volume',
templateUrl: './volume.component.html',
styleUrls: ['./volume.component.scss'],
encapsulation: ViewEncapsulation.None
})
or by using /deep/ in your stylesheet, as described here:
https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep

Overwriting styles from Bootstrap in an angular2 component-stylesheet

I have an angular2 application build with angular-cli containing several components. Each component has a referenced stylsheed (scss).
Unique styles from those stylesheets are correctly applied to the component-template.
What I cannot do is overwrite styles from external css's which are included in the angular-cli from those component-stylesheets.
As soon as I move the style to the central styles.scss it works.
My angular-cli.json looks like this:
"styles": [
"../node_modules/bootstrap/dist/css/bootstrap.css",
"../node_modules/bootstrap-datepicker/dist/css/bootstrap-datepicker.css",
"../node_modules/bootstrap-timepicker/css/bootstrap-timepicker.css",
"styles.scss"
],
Any Ideas how I can overwrite the bootstrap-css in the component.scss?
I've also posted this question as a possible bug to the angular-cli project and got the hint I needed:
Emulated view encapsulation (the default) emulates the behavior of Shadow DOM by preprocessing (and renaming) the CSS code to effectively scope the CSS to the component's view. If those classes got renamed for this behaviour, it cannot work and I cannot override styles from ie. bootstrap.
If I now set the encapsulation in the component to none, it works and I can override the styles in the component.scss.
#Component({
selector: 'app-generic-view',
templateUrl: './generic-view.component.html',
styleUrls: ['./generic-view.component.scss'],
encapsulation: ViewEncapsulation.None
})

AngularJS 2 styleUrls: What's up with concatenation?

My AngularJS 2 application has several style files which I concatenate with a gulp task. That's all fine, since they'll end up in a big file I send to the browser in production. My question is about the Angular 2 #Component and its styleUrls attribute.
#Component({
selector: 'hero',
templateUrl: 'hero/hero.template.html',
styleUrls: ['hero/hero.component.css'],
inputs: ['hero']
})
Thanks to shadow DOM emulation in default mode (emulated) the styles defined in the hero/hero.component.css are applied only to the component just like I want. My question is, what happens with concatenation? I cannot bundle all the CSS files specified in the multiple styleUrls since we'd be defeating the purpose of encapsulation: the styles for a component would leak to the whole document. However, I don't want either to make a call in production for every CSS file a component needs. How can I concatenate those styles (and possibly minify them) so the client gets them all in a single call, and still preserve encapsulation?
The template and css files can be bundled along the js files using a system js plugin.
import { Component } from '#angular/core';
import html from './hero/hero.template.html!text';
import css from './hero/hero.component.css!text';
#Component({
selector: 'hero',
template: html,
styles: [css],
})
export class HeroComponent implements {
}

Pseudo elements in Angular5

Why are regular pseudo-classes from CSS in Angular5 not working properly? I know that you can mimmic their behaviour using the Angular event handlers like (click)="function1()" or (mouseenter)="function2()".
What is the reason we can't use regular CSS pseudo-classes in Angular?
CSS is working just fine with Angular.
That said, Angular encapsulates the CSS for the current component you're working on (without you having to worry about that). It's a feature that you get with shadow DOM but as not all the browsers supports that, Angular is emulating it by adding properties on your components like that:
<div _ngcontent-c6>... your content ...</div>
And the original CSS you wrote is then changed by angular to:
div[_ngcontent-c0] {
color: red; // for example
}
So if you want to write some CSS that will affect other components and not just the current one, you should set the view encapsulation to none:
#Component({
selector: '...',
templateUrl: '',
styleUrls: [''],
encapsulation: ViewEncapsulation.none
})
Or, if you have an angular cli project, you can also define the global styles in: styles.scss (or .css) file which doesn't have any view encapsulation.
See more here: https://angular.io/guide/component-styles#view-encapsulation
(But before turning that feature off, think twice about it as it's really useful)

Resources