Css issue in angular 6 - css

In my angular 6 app. There are many components I have created. For display data I have used ng2-smart-table.
I have some specific requirement to hide default pagination bar. And display custom pagination.
For that I have just set css in component's SCSS file.
::ng-deep .ng2-smart-pagination-nav {
display: none
}
But this is also affects in all other components also.
Till I know and RND on that, In angular we used each component has their each scss file. So my question is why this css affect to all other component also? And how to prevent in this issue ?

The /deep/ combinator works to any depth of nested components, and it
applies to both the view children and content children of the
component
Use
:host Use the :host pseudo-class selector to target styles in the
element that hosts the component (as opposed to targeting elements
inside the component's template).
:host ::ng-deep .ng2-smart-pagination-nav {
display: none
}

Related

Angular - How To Organize CSS Overrides Across Components For The App

I'm relatively new to angular. In the process of converting a React app to Angular just for learning purposes. I have a parent component that has a button (Custom Button Component). This button when loaded in the parent should be hidden and on hover should show the button. So you probably get an idea that I have some CSS selectors related to the parent component that override the child CSS. First should be display: none and then on hover I change it to display: flex
So the first problem I encountered was that I could not override the child CSS from the parent CSS. After reading all kinds of posts I moved the CSS overrides from the parent CSS to the global stylesheet and also added encapsulation: ViewEncapsulation.None to the child component.
Next thing I noticed is that the align-items: center was not working on the child. First thought I had that guess I have to add that part to the global styles also? but what I really need to know is that is this the norm in Angular? If yes, then some things don't make sense to me. These styles are really not global. They are only related to the parent component then it seems kind of weird to add those to the global stylesheet.
In regards to the align-items not aligning the child (custom-button), I believe that happens because of the extra div being added around the button. So how do you handle such situations?
Appreciate any advice/tips.
Thank you!
You can overwrite children CSS classes from the parent componet. this is the way:
Assuming your child component have this CSS
.child-class {
background-color: blue;
}
When you use this component the background color will be blue. But if you want to change that color to RED. In the parent component where you want the change you need to do this:
In your parent component
:host {
::ng-deep{
.child-class {
background-color: red;
}
}
}
:host this refers to the component's HTML tag (that is created by Angular, in your case the tag of the component that contains the app-custom-button). Also you can apply css to the component tag.
for example:
:host{
width: 100vw;
height: 100vh
}
And with ::ng-deep you can overwrite ALL styles inside your compoent. Does not matter if is a style from your child compoenent, grandchild, great-great-grandson, etc... even if its a component from an external library.
So... For example you can have the "custom background color as blue" then in one component you can keep that color but in other component you can change the color to red and in other component you can change the color to green....
Angular have the concept of ViewEncapsulation. By default, the value is set to ViewEncapsulation.Emulated and the css you put in the component is specific to the component and only to this component. The CSS will not be applied to the child components.
You can switch to ViewEncapsulation.None and you will disable this behavior and all the css rules in your css file will be applied to all your components in the application, and maybe you don't want this behavior. That's why I advice you to leave this option.
The other option you got is to put your specific css rule in src/style.css (if you didn't modify the default path). All css rules put in this file will be applied for all the application and you can keep the ViewEncapsulation of your component.
For align-items, i think you are right : the app-custom-button is wrapping your button, so you need to set a width: 100% to your button, then eventualy resize your app-custom-button

How to change styles of child mat angular component?

As angular official documentation says, ::ng-deep , >>>, /deep/ is deprecated and will be removed soon:
https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep
If i am using mat components like <mat-checkbox> or a more comprehensive one like <mat-table> how could I have some changes to that component from parent?
Should I cancel view encapsulation for that component and write
styles in .SCSS files?
How do I edit styles of inner material angular component if deep selector is going to be removed?
What is the proper way to do that?
As the mention document says you can use the combination of ::ng-deep with :host and it will be OK in this way.
In order to scope the specified style to the current component and all its descendants, be sure to include the :host selector before ::ng-deep. If the ::ng-deep combinator is used without the :host pseudo-class selector, the style can bleed into other components
:host /deep/ h3 {
font-style: italic;
}
But, you also can use the custom CSS class & id to apply your custom css on .CSS or .SCSS files on the Angular Material Components. using .class & #id in combination with mat default classes works.
In addition you can use custom Angular material classes in your componnent style files ( .CSS or .SCSS) to override the like this:
.app-component-style {
/* All the CSS here */
.mat-tab-group .mat-tab-label {color: green;}
}
So, keep using it as Dudewad mention here too:
https://stackoverflow.com/a/49308475/4185370

Override Angular Material CSS differently in different components

I have two components with tab groups in them. One is a main page and I have overwritten the css to make the labels larger, done using ViewEncapsulation.None. The other is a dialog, and I want to keep it small but still apply some other custom styles to it.
When I open the dialog after visiting the other tabs page, it copies all the styles, which I have figured is because ViewEncapsulation.None bleeds CSS but not exactly as expected.
Is there anyway to override Angular Material styles without changing ViewEncapsulation so that I can keep the two components separate?
Solution 1: you can put all elements of your component into a parent element with a css class and override the material style into it.(it's custom capsulation)
Note: ViewEncapsulation is none here.
component.html
<div class="my-component__container">
<!-- other elements(material) are here -->
</div>
component.scss
.my-component__container{
// override material styles here
.mat-form-field{...}
}
Solution 2: use /deep/(deprecated).(use ::ng-depp insteaded)
:host /deep/ .mat-form-field {
text-align: left !important;
}
Solution 3: don't change ViewEncapsulation , then:
:host {
.my-component__container{}
}
if you would like to customise your Angular material components and provide your own stylings, I have the following suggestions. You may use one of them.
1) Overwrite the classes on your main style.css (or style.scss, whichever you are using). If you are wondering, it is the one that is on the same directory level as your index.html, main.ts, package.json, etc. You might need to add the !important declaration.
For instance,
.mat-form-field-label {
color:blue!important;
}
2) Customising the various Angular Material directive (such as MatPlaceholder) by providing a custom class.
For instance, when we use the MatPlaceHolder, and on the component.html template,
<mat-placeholder class="placeholder">Search</mat-placeholder>
On your component.css, we can then supply the css properties to the placehodler class
.placeholder {
color: green
}
Note:
Alternatively you may use ::ng-deep, but I would strongly suggest using ::ng-deep as it will soon be deprecated.
::ng-deep .mat-dialog {
/* styles here */
/* try not to use ::ng-deep */
}
You can use ::ng-deep. Refer NgDeep

Using Angular component name in Less stylesheet don't match generated DOM

I'm leaning Angular by following Udemy course and I have this style:
server dl {
display: flex;
}
and server component and it don't work. The style is not applied to html. Because generated style look like this:
server[_ngcontent-c1] dl[_ngcontent-c1] {
display: flex;
}
and DOM look like this:
<server _ngcontent-c0="" _nghost-c1="">
<dl _ngcontent-c1="">
<dt _ngcontent-c1="">Plantform</dt>
<dd _ngcontent-c1="">Linux x86_64</dd>
</dl>
</server>
_ngcontent-c0 instead of _ngcontent-c1, why this is happening? Why the style don't match the DOM?
I'm using Angular app using generated by CLI with Less (but I've created component by hand using server as selector, the same happen if name is app-server).
Why this attribute selectors are added? What about if I use this component in different place? I want to match all elements inside component that's why I've added server as selector to always match all inside this component.
How can I use component name that is added to html as root for my whole style? Or is this not good practice in Angular and this is handled other way, if so can someone explain?
Every element of a component is scoped-automagically / polyfilled by angular (in accordance with css spec for scoping) using those attributes you noticed. So basically, you don't have to write component-name element when you write css for that component but you can just write:
dl {
display: flex
}
Angular will make sure that this style is only applied to dl inside server by using the generated attributes, it is essentially a polyfill for css scoping. If all your targeted browsers support css scoping natively, you can even set ViewEnacpsulation.Native
In some cases where you decide to style the root element, you have to use the special selector :host
The :host selector is the only way to target the host element. You
can't reach the host element from inside the component with other
selectors because it's not part of the component's own template. The
host element is in a parent component's template.
So instead of writing server {background: red} you will write :host {background: red}
This is also inline with css spec for scoping.
Read more about CSS coping and component based CSS to know more about this strategy.
As a primer read the base documentation in Angular
Also, note that you can add your css to any global stylesheet like the way you did:
server dl {
display: flex
}
Which way to go largely depends on how you plan to manage and scale css.
You can use at .TS file below the class.
This is delete all this _ngcontent
#Component
selector,
template,
styles,
This code encapsulation: ViewEncapsulation.None

How do I prevent Angular component styling override from carrying over to other components?

I have a couple Angular components that route back and forth to one another. They both have mat-form-field's. In one component, I am overriding the styling of the underline component like so:
::ng-deep .mat-input-underline {
display: none;
}
When I click on the link to go back to the other component, the styling as defined as above carries over and the underline components are gone. I tried to add styling like:
::ng-deep .mat-input-underline {
display: revert;
//or
display: unset;
//or
display: initial;
}
But none of them work. How can I override the material design styling on just one component but not the others?
Your issue is caused by ::ng-deep, which will apply style to all .mat-input.underline elements in the page once the component has been loaded and style injected.
If you really want to keep the ::ng-deep combinator, you can add the :host selector to prefix your rule, which will target the host element and not leak the css to other components (apart from child components)
:host ::ng-deep .mat-input-underline
{
display: none;
}
https://angular.io/guide/component-styles#host
Style your component this way, this styling would not leak to the child component. Use ::ng-deep within :host but exactly like I have done below.
:host {
::ng-deep p, .py-8 {
margin: 0 !important;
}
}
I'm assuming you are using Angular Cli to generate your components...
You need to Emulate the encapsulation property on your Component. Although Angular defaults to 'Emulate'. (Thanks David, for correcting me).
In a nutshell, Emulated allows your component to make use of global styles, while keeping its local styles to itself.
#Component({
selector: 'app-child-component',
template: `<div class="parent-class">Child Component</div>`,
encapsulation: ViewEncapsulation.Emulated
})
Also, ::ng-deep is meant to pass styles from parents to children. So if you are trying to keep your child elements from adopting the styles of their parents, using that is working against you.
"/deep/" is deprecated and "::ng-deep" is the way but be careful.
Please go through below official documentation for detailed information.
https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep

Resources