Custom Styling of mdToolTip - css

I have the following code in an Angular project
<input class="form-control" type="number" [(ngModel)]="cons.failPercent" [ngModelOptions]="{standalone: true}"
mdTooltip="Typically valves can be repaired three times before they need to be replaced"
mdTooltipPosition="right"
autofocus/>
In my component I have
#Component({
templateUrl: './ownership-form.component.html',
styleUrls: ['./ownership-form.component.css'],
encapsulation: ViewEncapsulation.None
})
and in my CSS I have
.md-tooltip{
color:yellow !important;
height:auto;
}
But it does not appear to be styling the tooltip. How can I fix this?

Depending on your Angular version you'll need to use the /deep/ or ::ng-deep combination selectors to circumvent encapsulation. Alternatively, set the styling on your global stylesheet (commonly styles.scss).
Angular 2:
/deep/ .md-tooltip { ... }
Angular 4.3+:
::ng-deep .md-tooltip { ... }
More info at Hackernoon

I would personally scope your styles to the component in question.
Angular < v4.2
:host /deep/ {
.md-tooltip { ... }
}
:host >>> {
.md-tooltip { ... }
}
Angular >= v4.2
:host ::ng-deep {
.md-tooltip { ... }
}
If you remove your encapsulation from the component. The styles should still work. By adding ::ng-deep inside the :host(..) it will emulate global css. But only in a downward piercing direction.
Angular is trying to promote component level styles. I would avoid moving code to the global stylesheets. If you visit a route which does not require the component in question then you are instantiating (loading code) for no reason.

Related

Styling child components template from parent component css angular

How to force CSS of child component from parent using ::ng-deep or something?
I have parent component where I put child component:
....parent.component...
<app-likes></app-likes>
.....parent.component......
Not inside that likes component there is he following HTML:
<div class="mainDiv">
<div class="secondDiv"><i class="far fa-heart fa-3x"></i></div></div>
Now I want to set color of fa-heart class to white from parent parent.component.css.
How can I do that?
You can do this way, in the css of the parent component:
parent.component.css:
:host ::ng-deep .fa-heart {
color: red;
}
or
:host ::ng-deep app-likes .fa-heart {
color: red;
}
Well I will go against the folks above and suggest that you don't do this.
If you consider the component an isolated building block in your app, you would consider it an advantage, that it looks the same in every place you use it. Using ::ng-deep to override this behaviour will cause you trouble in larger apps.
Angular promotes using #Inputs as the interface of passing data into the component. My suggestion is to use #Input to modify the view. Or, if in larger contexts you can use Dependency Injection to provide a token that specifies a theme for all children of a component.
<app-likes theme="white"></app-likes>
#Component({selector: 'app-likes'})
class AppLikesComponent {
#Input() theme: string;
#HostBinging("class") get themeBinding() {
return 'theme--' + this.theme;
}
}
You could set the ViewEncapsulation option in the parent component to remove the shadow DOM. This essentially allows the child component to use the selector definitions from the parent component.
Try the following
Parent component
import { Component, ViewEncapsulation } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ],
encapsulation: ViewEncapsulation.None // <-- no shadow DOM
})
export class AppComponent {
}
Parent CSS
.fa-heart {
color: white;
}
Working example: Stackblitz

How do I style child component from parent's SCSS without ng-deep?

I've been trying to style a BoxedComponent style from HeaderComponent without using ::ng-deep, but I'm not finding a way to so properly.
The BoxedComponent component class contains nothing different but a ViewEncapsulation.None.
#Component({
selector: 'labs-boxed',
templateUrl: './boxed.component.html',
styleUrls: ['./boxed.component.scss'],
encapsulation: ViewEncapsulation.None,
})
export class BoxedComponent {}
HTML
<div class="boxed">
<ng-content></ng-content>
</div>
I created two classes in its SCSS file to use everywhere, but I realized I couldn't still stylize the responsiveness of the component due to the same problem.
.boxed {
/* rules */
}
.tall .boxed {
height: 500px;
width: 360px;
}
.squared .boxed {
height: 340px;
width: 340px;
}
In HeaderComponent's HTML file, I am making use of labs-boxed as follows:
<div id="who-we-are" class="d-flex justify-content-around">
<labs-boxed [ngClass]="'tall'">
<p>
...
...
...
So far it works, but then entering in the SCSS file, I have attempted many ways to access lab-boxed's styles and changing it:
.boxed { ... }
.tall .boxed { ...}
and so on, but without success.
How can I do it, please?
Since BoxedComponent has ViewEncapsulation.None all rules defined in boxed.component.scss becomes global. When HeaderComponent has default encapsulation, all rules defined in header.component.scss are isolated from global scope and becomes specific to HeaderComponent. As a matter of fact ng-deep works by making single rules global. In other words it removes rules from isolated scope and puts into the global scope and it is the only way of making a single rule global within an encapsulated styles file. Without help of ng-deep you can override child component styles in following ways;
Apply another global style to child and add related styles to global; styles.scss file.
in header.component.html
<labs-boxed class="custom-box-style">
in styles.scss
.custom-box-style .boxed {
// new rules
}
Programatically set styles on specific child instance.
in header.component.html
<labs-boxed #childEl class="squared">squared and red</labs-boxed>
in header.component.ts
#ViewChild('childEl', {read: ElementRef, static: true}) childEl: ElementRef;
ngAfterViewInit() {
const box = this.childEl.nativeElement.getElementsByClassName("boxed");
box[0].style.backgroundColor = "red"
}
Here is a demonstration of both approaches.

Grid Styling - Overwrite style of ag-grid

I have the following style:
.ag-theme-fresh .ag-row-selected {
background-color: #bde2e5;
}`
It comes from a css style file of a theme. But I want to overwrite it with this style:
.ag-theme-fresh .ag-row-even .ag-row-selected {
background-color: #1428df;
}
But it has not effect and my component uses the first style. How can I overwrite the first style 1? I tried with !important but it does nothing.
Should I define my custom style at the beginning of the css file?
UPDATE:
I found I can use the function gridOptions.getRowClass to set the style class to be used. But I would like to solve the issue central (for all the angular grids that I use in my application). Any idea?
You should use ViewEncapsulation
Just add to your component encapsulation: ViewEncapsulation.None:
import { Component, ViewEncapsulation } from "#angular/core";
#Component({
selector: '....',
templateUrl: '....',
styles: [`
.ag-theme-fresh .ag-row-selected {
background-color: #1428df !important;
}
`],
encapsulation: ViewEncapsulation.None
})
To override the ag-grid use you need to use ng-deep as the style defined in angular component do not overide ag-grid css
:host ::ng-deep .ag-header-cell-label {
justify-content: center;
}
update : this will make the style global. By changing the encapsulation set as none (ViewEncapsulation.None) at component will make style global as well.
if you are using sass or scss you could override in the style.scss/sass. this would be applicable at all places
#import "../node_modules/ag-grid-enterprise/dist/styles/ag-grid.scss";
#import "../node_modules/ag-grid-enterprise/dist/styles/ag-theme-alpine/sass/ag-theme-alpine-mixin";
.ag-theme-alpine {
#include ag-theme-alpine(
(
// use theme parameters where possible
alpine-active-color: #c066b2,
)
);
.ag-header-cell-label {
justify-content: center;
}
}
if you have need of doing at a specific grid, prefer custom class and make sub-class for the ag-grid.
You can also apply the styles globally and if you do so it will override the styles for all your ag-Grid components. This might not be an option if you are trying to style the components individually, but it's a good way to give a global base style override.
Also, you should try to use more specific selectors instead of using important.
Here is an example:
.ag-theme-alpine > .ag-row.ag-row-selected {
background : red;
}

Prevent global CSS being applied a component in Angular 5

In .angular-cli.json, I got some global styles:
"styles": [
"../node_modules/bootstrap/dist/css/bootstrap.css",
"../node_modules/font-awesome/css/font-awesome.css",
"../node_modules/ng2-toastr/bundles/ng2-toastr.min.css",
"styles.scss"
],
But I don't want any of them being applied to a specific component - is it achievable?
EDIT 1:
Unfortunately, overriding the CSS style in the component style won't work because the HTML in the template of the component is fetched from a Web API backend - I guess I can't realistically override every possible class/selector?
CSS cascades (hence the term, Cascading Style Sheets).
for full browser support your only option is to override selectors.
another option, not as common due to lack of support on IE and Edge,
is the all property.
html
<div class="component-container">
<!-- your components html template ... -->
</div>
css
.component-container {
all: initial;
all: unset;
}
Using component styles
For every Angular component you write, you may define not only an HTML template, but also the CSS styles that go with that template, specifying any selectors, rules, and media queries that you need.
One way to do this is to set the styles property in the component metadata. The styles property takes an array of strings that contain CSS code. Usually you give it one string, as in the following example:
#Component({
selector: 'app-root',
template: `
<h1>Test Text</h1>
`,
styles: ['h1 { font-weight: normal; }']
})
export class AppComponent {
/* . . . */
}
styleUrls
One or more URLs for files containing CSS stylesheets to use in this component.
styleUrls: string[]
styles
One or more inline CSS stylesheets to use in this component.
styles: string[]
You can use the :not selector in your global CSS.
You'd have to play around with it to get the desired behaviour but it should be something like this:
h1:not(.my-specific-class) {
font-size: 3rem;
}
You can use angular built in shadowDom API from view encapsulation. Which will make your component elements loaded inside a separate DOM tree so global css wont affect your component elements.
#Component({
selector: 'app-root',
template: `
<h1 class="head-app">Test Heading</h1>
`,
styles: ['./app.component.scss'],
encapsulation: ViewEncapsulation.ShadowDom
})
export class AppComponent {
/* . . .
You can define styles at component level using styleUrls property inside the scope of #Component. Please have a look at below code:-
#Component({
selector: 'app-manageUser',
templateUrl: './manageUser.component.html',
styleUrls: ['./manageUser.component.css'],
providers: [UserService]
})

matTooltipClass not applying css

I am attempting to apply some css changes to mat-tooltip from angular material 2 and found in the documentation a matTooltipClass that can then be selected in the css file to make changes. However, I am not able to get it working.
component.html :
<mat-cell
*matCellDef="let productInfo"
matTooltip="{{productInfo.description}}"
matTooltipClass="tooltip">
{{ productInfo.description}}
</mat-cell>
component.scss:
.tooltip {
background-color: red;
color: blue;
font-size: 20px;
}
You have to use ::ng-deep to override default CSS for material elements:
::ng-deep .tooltip {
background-color: red;
color: blue;
font-size: 20px;
}
In addition to what was stated above,
Here are two methods that worked for me:
-in the Component.scss:
::ng-deep mat-tooltip-component{
& .mat-tooltip{
color: green; // your custom properties here.
}
}
-Globally:
.mat-tooltip{ // making the font size on the mat-tooltip 1.5rem globally
font-size: 1.5rem;
&.exaggerated-tooltip{ // to modify the tooltip create a class like this
font-size: 2.5rem; // and use it like this: *matTooltipClass="exaggerated-tooltip"* in the
color: red; // component in which you are putting the tooltip
}
}
A blog post by Siderite (Styling Angular Material tooltips) provided an answer that worked for me. I am paraphrasing from the most-relevant portion of his post and I am using the matTooltipClass="tooltip" scenario described in the Question above:
[The .tooltip class definition] should either be in the global CSS
file (so it applies to everything) or your component should declare
encapsulation ViewEncapsulation.None. [If the .tooltip class
definition is in the global CSS file], then ensure the declaration of
the class is specific enough: try this:
mat-tooltip-component .mat-tooltip.tooltip {...}.
In my case, I had defined the .tooltip class in the global styles.scss file, and it wasn't working until I followed Siderite's suggestion and defined it like this:
mat-tooltip-component .mat-tooltip.tooltip {
color: blue !important;
}
This approach is avoids using ::ng-deep as suggested in the accepted Answer. Angular documentation states that approach is deprecated. I did find I needed to use !important, which some believe is bad style.
Angular material doc says matTooltipClass supports the same syntax as ngClass.
thus you might try [matTooltipclass]="'tooltip'"
<mat-cell
*matCellDef="let productInfo"
matTooltip="{{productInfo.description}}"
[matTooltipclass]="'tooltip'">
{{ productInfo.description}}
</mat-cell>
From the example provided in the website (https://material.angular.io/components/tooltip/examples):
import {Component, ViewEncapsulation} from '#angular/core';
/**
* #title Tooltip that can have a custom class applied.
*/
#Component({
selector: 'tooltip-custom-class-example',
templateUrl: 'tooltip-custom-class-example.html',
styleUrls: ['tooltip-custom-class-example.css'],
// Need to remove view encapsulation so that the custom tooltip style defined in
// `tooltip-custom-class-example.css` will not be scoped to this component's view.
encapsulation: ViewEncapsulation.None,
})
export class TooltipCustomClassExample {}
If you stick that encapsulation: ViewEncapsulation.None line there for your component where you want to use your custom tooltip class, it ought to work. It's how I fixed the issue on my end.
Seeing that ::ng-deep is depricated now, best seems to be to add encapsulation: ViewEncapsulation.None, in your component decorator under your styleUrls line
Just be careful that all your css classes will be global then, so make sure your classes in that component have unique names if you do not want to overwrite the classes in other components accidentally
I found out there is a div element down the body with class="cdk-overlay-container". I considered its z-index. it was 1000 below the z-index of my modal. I made it the same as my modal's z-index, i.e. 1050. And it is working. I also had to put ::ng-deep before my class in CSS file.
::ng-deep .cdk-overlay-container {
z-index: 1050;
}
In case your project prohibits to use: ::ng-deep, you can use
encapsulation: ViewEncapsulation.None
in the TS file.

Resources