Isolate bootstrap CSS to one angular component? - css

Is it possible to isolate Bootstrap's css file to one Angular component?
When including the file globally in styles.css or in .angular-cli.json, the global styles are causing issues with other components that should not be using bootstrap. I have tried to do this by importing it from the component's CSS file but the styles do not seem to render properly...
I am using Angular 5 and Angular Cli 1.7.2.

you can explicitly set the encapsulation strategy using the encapsulation property.Set it to ViewEncapsulation.Native for your case
#Component({
// ...
encapsulation: ViewEncapsulation.Native,
styles: [
// ...
]
})
export class HelloComponent {
// ...
}
Native - styles from main HTML do not propagate to the component. Styles defined in this component's #Component decorator are scoped to this component only.
Refer this View Encapsulation.

Related

When and why should we use View Encapsulation in angular

When working in angular is there a particular rule or guideline that should be used in deciding when to use and why to use View Encapsulation?
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
encapsulation: ViewEncapsulation.None /*What is the use of this line*/
})
Can someone please explain in simple ways?
Codecraft.TV has an amazing article on ViewEncapsulation that you can refer to get a better understanding.
To just summarize it:
ViewEncapsulation.Emulated: Angular changes our generic css class selector to one that target just a single component type by using automatically generated attributes.
Any styles we define on a component don’t leak out to the rest of the application but with ViewEncapsulation.Emulated our component still inherits global styles.
ViewEncapsulation.Native: If we want Angular to use the shadow DOM we can set the encapsulation parameter to use ViewEncapsulation.Native
With ViewEncapsulation.Native styles we set on a component do not leak outside of the components scope.
This is great if we are defining a 3rd party component which we want people to use in isolation. We can describe the look for our component using css styles without any fear that our styles are going to leak out and affect the rest of the application.
However with ViewEncapsulation.Native our component is also isolated from the global styles we’ve defined for our application. So we don’t inherit the global styles and have to define all the required styles on our component decorator.
Finally ViewEncapsulation.Native requires a feature called the shadow DOM which is not supported by all browsers.
ViewEncapsulation.None: If we don’t want to have any encapsulation at all, we can use ViewEncapsulation.None.
If we don't encapsulate anything, the style we defined in the component will leak out and started affecting the other components.
Some other resources that you might want to have a look into:
VIEW ENCAPSULATION IN ANGULAR - By Thoughtram
View Encapsulation by Rangle.IO
Scoping Your Styles in Angular With ViewEncapsulationView
Diff between ViewEncapsulation.Native, ViewEncapsulation.None and ViewEncapsulation.Emulated
Let's take one example where we have one parent and one child component with their own html, ts, css files.
Suppose in parent component's html you referenced child component like below-
parent.component.html -> <app-child> </app-child>
Now, if you create and add any similar styles like parent.component.css file in child.component.css (let's take <p> tag as an example) then those will get added to each component seperately even if all angular component's html gets rendered on single page.
So now you will have seperate styles for <p> in child component.(Behind the scene angular adds one random_atttr to each component and then to all elements inside that component)
This behaviour of angular, comes in view encapsulation. Used by angular like shadow DOM techonlogy which is not supported by all broswers but angular does it like this.
ViewEncapsulation has 3 options -
encapsulation: ViewEncapsulation.None,
ViewEncapsulation.Emulated, (-- this is default)
ViewEncapsulation.Native (-- only applies to browsers with shadow DOM technology)<br>

Angular 6 alterante way to global css

I'm using Handsontable in one of my component, and it forces me to include it's css globally in my angular.json file
"styles": [
"./src/styles.scss",
"./node_modules/handsontable/dist/handsontable.full.css"
],
and it affects my calendar component all over my application.
How can i include this css only for that handsontable component and disable it for all other components.
writing import in handsontable component scss file doesn't work.
Thanks in Advance.
This works as below. Pay attention to encapsulation: ViewEncapsulation.None. This will disable default Emulated DOM, so that styles of this component, will be applicable to children as well. Other wise, by default Emulate DOM, protects scopes of each component (that is why it was not working in your case).
Refer to documentation also.
However, that won't fix your problem actually. Because, as per documentation:
[ViewEncapsulation] None means that Angular does no view encapsulation. Angular adds the CSS to the global styles. The scoping rules, isolations, and protections discussed earlier don't apply. This is essentially the same as pasting the component's styles into the HTML.
What effectively means, that the output will be in global scope any way.
So probably it is easier just add once in your main styles.scss:
#import '~/handsontable/dist/handsontable.full.css';
Working with ViewEncapsulation.None encapsulation.
// component.ts
#Component({
selector: 'app-table',
template: `<hot-table ....></hot-table>`,
styleUrls: ['./table.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class TableComponent {
...
}
// component.scss
#import '~/handsontable/dist/handsontable.full.css';
You can try the following
#Component({
selector: 'app-home-component',
template: '<div></div>',
styleUrls: [
'path/handsontable.full.css',
'./home.component.css'
],
})
export class HomeComponent{}

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
})

Resources