Angular host element: what is the easiest way to style on focus - css

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

Related

How to change the sticky header background color on scroll in angular 11

Tried to change the background color on scroll to the sticky header but not working. How to do it? when I scroll to the bottom of the body I need to change the header background color. How to do it?
app.component.html
<div class="header sticky">
</div>
app.component.css
.sticky {
position: -webkit-sticky;
position: sticky;
top: 0px;
}
Demo: https://stackblitz.com/edit/sticky-header-hyibz9?file=app%2Fheader%2Fheader.component.css
You can use ngClass for this and HostListener to check if user scrolled at the buttom
html
<div class="header sticky" [ngClass]="isBottom ? 'bottom' : 'top'">
</div>
ts
import { Component, OnInit, HostListener } from '#angular/core';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
isBottom: boolean;
constructor() {}
ngOnInit() {}
#HostListener('window:scroll', [])
onScroll(): void {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight) {
this.isBottom = true;
} else {
this.isBottom = false;
}
}
}
css
.sticky {
position: -webkit-sticky;
position: sticky;
top: 0px;
}
.header {
height: 50px;
}
.top {
background-color: blue;
}
.bottom {
background-color: yellow;
}
import { Component, OnInit, HostListener } from '#angular/core';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
isBottom: boolean;
constructor() {}
ngOnInit() {}
#HostListener('window:scroll', [])
onScroll(): void {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight) {
this.isBottom = false;
} else if (window.scrollY) {
this.isBottom = false;
} else {
this.isBottom = true;
}
}
}

Is it possible to use styles from an Angular service in scss?

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>

Lit-element not applying classes static get styles

I am making a simple component to test newest Lit-element a checkbox.
Upon testing static get styles only the first element I style is shown, I have seen in the documentation what I am trying should be correct, may I have some help?.
this is my component:
import {LitElement, html, css} from 'lit-element';
class CheckboxMJ extends LitElement {
static get properties(){
return{
check:{type:Boolean},
name:{type:String},
}
}
static get styles() {
return css`
.checkWrapper{
font-family: Roboto;
background-color: red;
font-weight: 500;
font-size:14px;
color:#283D3B;
border:none;
outline:none;
height: 150px;
width: 300px;
border-radius: 3px;
overflow:hidden;
padding:3px;
}
input[checkbox i]{
background-color:red;
}
`;
}
constructor(){
super();
this.check=false;
this.name="";
}
render() {
return html`
<div class="checkWrapper">
<input class="checkbox-mj" type="checkbox" name="${this.name}" value="${this.check}"> ${this.name}
</div>
`
}
}
customElements.define('checkbox-mj', CheckboxMJ);
I have been encountering this issue several times with other components, kept changing order, and names of classes until it worked but I feel so lost about how this should be done right, please somebody enlighten me on how to use this feature correctly.
You have to keep in mind that checkboxes are very difficult to stylize. Many properties simply have no effect on this input. On the other hand you have to use a standard css selector to stylize the checkbox input[type="checkbox"].
If you want the check property to be reflected in your checkbox you must do it this way:
?checked="${this.check}"
Look at this guides for more information https://lit-element.polymer-project.org/guide/templates (Bind properties to templated elements).
import {
LitElement,
html,
css
} from 'lit-element';
class CheckboxMJ extends LitElement {
static get properties() {
return {
check: {
type: Boolean
},
name: {
type: String
},
}
}
static get styles() {
return css `
.checkWrapper{
font-family: Roboto;
background-color: red;
font-weight: 500;
font-size:14px;
color:#283D3B;
border:none;
outline:none;
height: 150px;
width: 300px;
border-radius: 3px;
overflow:hidden;
padding:3px;
}
input[type="checkbox"]{
margin:1rem
}
`;
}
constructor() {
super();
this.check = true;
this.name = "Check";
}
render() {
return html `
<div class="checkWrapper">
<input class="checkbox-mj" type="checkbox" name="${this.name}" ?checked="${this.check}"> ${this.name}
</div>
`
}
}
customElements.define('checkbox-mj', CheckboxMJ);

Style host element on Stencil component based on class

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

How to css style angular2's Ng2-completer plugin input box and dropdown color?

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/

Resources