In Stencil when you have set shadow: true, styling the host element is as follows
:host {
color: red;
}
This works. But now I have the following component
#Component({
tag: 'my-component',
styleUrl: 'my-component.scss',
shadow: true
})
export class MyComponent {
#Element() host: HTMLElement;
render() {
this.host.classList.add('is-test');
return <div>Test</div>;
}
}
in which I add the is-test class to the host element. Now, to apply styling based on that class I added the following
:host {
color: red;
&.is-test {
background-color: green;
}
}
I see is-test class on my-component element, but the background-color: green style is not applied. I must be doing something wrong here, any help would be appreciated!
You can use :host():
:host {
color: red;
}
:host(.is-test) {
background-color: green;
}
By the way: If you want to set the class (or any attribute) on the host element, you can use the <Host> functional component:
import { Host } from '#stencil/core';
// ...
render() {
return <Host class="is-test"><div>Test</div></Host>;
}
Related
I have a change-color.service.ts that has the following:
public defaultStyles = {
firstDesignBackgroundColor: '#a31329',
firstDesignFontColor: '#ffffff',
secondDesignBackgroundColor: '#d1cfcfff',
secondDesignFontColor: '#000000'
};
now I will like to add to my style.scss for the statement
:host ::ng-deep th span#optimize-checkbox-header .mat-checkbox label.mat-checkbox-layout .mat-checkbox-inner-container.mat-checkbox-inner-container-no-side-margin .mat-checkbox-frame {
border: 2px solid #fff !important;
}
replace the #fff with firstDesignFontColor from the change-service. Do you know how I can create this dependency? Is this possible at all?
There is actually a way to realize it with css variables that I will post here as a second answer.
You can change css variables from JavaScript code, so if you use variables for your class like this simplified example:
:root {
--bg-color: red;
}
.test {
background-color: var(--bg-color);
}
then you can change this from your ChangeColorService
interface Colors {
background: string;
}
#Injectable()
export class ChangeColorService {
colors$ = new BehaviorSubject<Colors>({ background: 'red' });
constructor(#Inject(DOCUMENT) private document: Document) { }
change(colors: Colors) {
const root = this.document.documentElement;
root.style.setProperty('--bg-color', colors.background);
this.colors$.next(colors);
}
}
Full example:
https://stackblitz.com/edit/angular-change-css-variable?file=src/app/app.component.ts
No that's not possible. What is possible, is to use style bindings.
class YourComponent {
styles: any;
constructor(private color: ChangeColor) {}
ngOnInit() { this.styles = this.color.defaultStyles; }
}
<div [style.background-color]="styles.firstDesignBackgroundColor"></div>
Try to change styling on focus of the host element. While the following construction works fine in combination with /deep/, it does not work for the host element itself. What's wrong with the CSS code?
:host {
background-color: white;
border: 1px solid lightgray;
padding: 1px 0;
display: inline-block;
}
:host:focus {
border: 2px solid lightskyblue;
}
Thanks for any help.
You could do it programmatically, with a HostListener, Renderer2 and ElementRef:
import { Component, ElementRef, HostListener, Renderer2 } from '#angular/core';
#Component({
selector: 'button[app-button]',
template: '<ng-content></ng-content>',
styleUrls: ['./button.component.css']
})
export class ButtonComponent {
constructor(
private el: ElementRef,
private renderer: Renderer2
) {}
#HostListener('focus', ['$event.target'])
onFocus() {
this.renderer.setStyle(this.el.nativeElement, 'background-color', 'red');
}
#HostListener('blur', ['$event.target'])
onBlur() {
this.renderer.setStyle(this.el.nativeElement, 'background-color', 'buttonface');
}
}
Or you could just use the :host pseudo selector and wrap the :focus in brackets in your component's stylesheet:
:host(:focus) {
background-color: red;
}
Here's an example: stackblitz.
Instead of using the renderer, you can just use hostlistener and hostbinding.
#HostBinding('class.focus') public focus: boolean = false;
#HostListener('focus', ['$event.target']) public onFocus(): void {
this.focus = true;
}
#HostListener('blur', ['$event.target']) public onBlur(): void {
this.focus = false;
}
in an Angular application I have a component with <ng-content></ng-content>. I added the scss rules for content that will be put inside the ng-content, but they are ignored. I tried to solve using :host, but it doesn't work.
https://stackblitz.com/edit/angular-ewqhzj
Wrapper component:
<app-embed>
<p>Hello world!</p><h1 class="toBeColored">toBeColored</h1>
</app-embed>
Styles in embed component:
:host {
border: 5px solid red;
padding: 15px;
display: block;
.toBeColored {
color: pink;
}
}
The problem is that the pink color of 'toBeColored' string is not set
Try this
:host ::ng-deep{
border: 5px solid red;
padding: 15px;
display: block;
.toBeColored {
color: pink !important;
}
}
and remove encapsulation statement and try ti build
encapsulation: ViewEncapsulation.Native
Try adding encapsulation: ViewEncapsulation.Native to your embed component like
import { Component, OnInit, ViewEncapsulation } from '#angular/core';
#Component({
selector: 'app-embed',
templateUrl: './embed.component.html',
styleUrls: ['./embed.component.scss'],
encapsulation: ViewEncapsulation.Native
})
export class EmbedComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
You can't achieve that with a clean way.
A workaround would be to create global css :
:host {
...;
::ng-deep .toBeColored {
color: pink;
}
}
But it will be deprecated. See this issue
::ng-deep is going to hold the web record for long-lived deprecated API.
You should be able to apply the styles in the parent component that projects the content into the ng-content tag. The angular styles isolation appears to consider the content to be part of the component where the HTML is declared.
https://stackblitz.com/edit/angular-ivy-q9dn68
I am using angular2/4's Ng2-Completer plugin and am having trouble with styling of the component. I want to change the background dropdown to "red" and the input box to be blue.
The following is my plunkr:
https://plnkr.co/edit/sVnfpBiEb5jBdtul4ls9?p=preview
I tried to include the following CSS, but it does not appear to impact anything:
.completer-row {
display: inherit;
background:blue;
}
.completer-selected-row {
background-color: lightblue;
color: yellow;
}
.completer-row p {
position: relative;
top: 50%;
transform: translateY(50%);
}
.completer-dropdown-holder {
position: absolute;
background: red;
}
.customid {
background:blue;
}
My component:
import { Component } from '#angular/core';
import { CompleterService, CompleterData } from 'ng2-completer';
import {Observable} from 'rxjs/Observable';
import 'rxjs/Rx';
#Component({
selector: 'my-app',
styleUrls: [
'./app.component.css'
],
template: `<h1>Search color</h1>
<ng2-completer id="customid" [(ngModel)]="searchStr" [datasource]="searchData" [minSearchLength]="0" [clearSelected]="true" (selected)="onSelected($event)"></ng2-completer>
<p>Selected: {{selectedColor}}</p>
`
})
export class AppComponent {
protected searchStr: string;
protected dataService: CompleterData;
protected selectedColor: string;
protected searchData = ['red', 'green', 'blue', 'cyan', 'magenta', 'yellow', 'black'];
protected onSelected(item: CompleterItem) {
this.selectedColor = item? item.title: "";
}
}
You can use inputClass propery of ng2-completer.
For example with bootstrap:
<ng2-completer [inputClass]="'form-control form-control-inline'" ...></ng2-completer>
You can style the angular ng2 completer like this:
::ng-deep .completer-row{
}
Angular 2 have a safety feature where CSS only work on HTML files of their respected component. Or css have to go in the global styles.css file for global use. However you can force CSS to apply by adding hots: >>> .class-name this method will force the css to apply to a child component.
More info on this thread Angular 2: How to style host element of the component?
https://alligator.io/angular/styles-between-components-angular/
How can I pass data from angular tag to the styles in the #Component?
Here is my component:
import { Component, Input } from '#angular/core';
#Component({
selector: 'icon',
template: `<svg class="icon"><use attr.xlink:href="#{{name}}"></use></svg>`,
styles: ['.icon{width:{{size}}px;}']
})
export class IconComponent {
#Input() name: string;
#Input() size: any;
constructor() { }
}
I wanna set size property from component.
used in html file:
<icon name="logo" size="37"></icon>
Binding in styles is not supported. You can use style binding like
template: `<svg class="icon" [style.width.px]="size"><use attr.xlink:href="#{{name}}"></use></svg>`,
I'm actually surprised that I finally found a somewhat solid solution to this using a ngx-css-variables.
My use case is that I have a 3rd-party library, which creates many child components within itself, as it draws charts.
I needed to set the linear gradient with a url(#<uuid>).
CSS Template
/deep/ngx-charts-line-chart {
display: flex;
/deep/ngx-charts-chart {
display: flex;
div.ngx-charts-outer {
display: flex;
svg {
.line {
stroke: var(--gradient);
stroke-width: 4px;
}
}
}
}
}
Component
import * as uuid from 'uuid/v4';
...
private _linearGradientId = uuid();
get uuid() {
return this._linearGradientId;
}
get gradientCss() {
return {
'--gradient': `url(#${this.uuid})`
}
}
...
HTML Template
...
<ngx-charts-line-chart
[css-vars]="gradientCss"
...
<ngx-charts-line-chart>
You still have to deep style the component since it's components are not in your template, but ngx-css-variables will inject a function into the style property, which seems hacky, but it works!
So now the stroke comes from that dynamic function at runtime. Super cool. I wish angular supported this natively.