How to dynamically change CSS in :host in angular 2? - css

How do I dynamically change CSS properties of a component host?
I have a component and in it's CSS I have given it a stlye:
:host {
overflow-x: hidden
}
On a button click from child component, I need to add overflow-y: hidden to the host component.
How do I achieve this behavior?

Here is a working example.
Use the following HostBinding:
#HostBinding('style.overflow-y') overflowY = 'scroll';
This would give the following component:
#Component({
selector: 'my-app',
template: `
<div>
<button (click)="addStyle()">Add Style</button>
<h2>Hello</h2>
</div>`, styles: [
`
:host {
overflow-x: hidden;
height: 50px;
width: 200px;
display: block;
}
`,
],
})
export class App {
name: string;
#HostBinding('style.overflow-y')
overflowY = 'scroll';
constructor() {
}
addStyle() {
this.overflowY = 'hidden';
}
}

Related

Calling typescript component function to scss file (Angular)

I'm trying to call this auto detect function from my component.ts file to my .scss file and I don't know how to or if it is even possible.
example.component.scss
.content {
display: flex;
align-items: center;
text-align: center;
height: getScreenHeight; <--- ERROR
width: getScreenWidth; <--- ERROR
}
example.component.ts
import { Component, OnInit, HostListener } from '#angular/core';
#Component({
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.scss']
})
export class exampleComponent implements OnInit {
public getScreenWidth: any;
public getScreenHeight: any;
constructor() { }
ngOnInit(): void {
this.getScreenWidth = window.innerWidth;
this.getScreenHeight = window.innerHeight;
}
#HostListener('window:resize', ['$event'])
onWindowResize() {
this.getScreenWidth = window.innerWidth;
this.getScreenHeight = window.innerHeight;
}
}
For reference I am using this functionality detection
Tried to call in html and in the .scss. Nothing has worked and have not found similar problems/questions
CSS is not that dynamic so approaching it from the SCSS file will give you problems, instead use inline styles for such problems.
<div class="content" [ngStyle]="{ height: getScreenHeight width: getScreenWidth }">
<!--content inside here-->
</div>

Angular ignores the animation duration

I have a sidebar component which take the sidebarExpanded state from Input(). Whenever the input changes, the animation is triggered correctly but the width change appears instantly. The same animation code is working in another component, so is not a common import problem. The problem persists in different browsers. What am I missing here?
Thank you.
sidebar.component.ts
import {
animate,
state,
style,
transition,
trigger,
} from '#angular/animations';
import { Component, Input, OnInit } from '#angular/core';
#Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.scss'],
animations: [
trigger('collapse', [
state('false', style({ width: '0' })),
state('true', style({ width: '25rem' })),
transition('false <=> true', animate(1000)),
]),
],
})
export class SidebarComponent implements OnInit {
constructor() {}
#Input() sidebarExpanded = true;
ngOnInit(): void {}
}
sidebar.component.html
<div class="sidebar" [#collapse]="sidebarExpanded"></div>
sidebar.component.scss
.sidebar {
display: flex;
flex-direction: column;
position: fixed;
top: 8rem;
bottom: 0;
background-color: var(--color-grey-dark-4);
box-shadow: var(--shadow-dark);
}
I figured out i had placed the animation both on the div containing the sidebar and on the sidebar itself. Removing the animation from the parent div solved my problem.

How to fix the height of Map to the screen size in Angular 4

I am creating the google map using Angular Google Map Component. I want to the google map to my screen size. I tried height:100%. But it doesn't work. Can anyone please tell me how to do it?
I followed this tutorial: https://angular-maps.com/guides/getting-started/
Map:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-map',
templateUrl: '<agm-map [latitude]="lat" [longitude]="lng">
<agm-marker
*ngFor="let m of markers;"
[latitude]="m.lat"
[longitude]="m.lng"
[label]="m.label"
[markerDraggable]="m.draggable">
<agm-info-window>{{m.tsunami}}</agm-info-window>
</agm-marker>
<agm-circle *ngFor="let m of markers;"
[latitude]="m.lat" [longitude]="m.lng"
[radius]="5000"
[fillColor]="'red'"
[circleDraggable]="false"
[editable]="false">
</agm-circle>
</agm-map>',
styleUrls: ['agm-map {
height: 100%;
}']
})
export class MapComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
I will use this selector name to another html
<div style="style:300px;">
<app-map></app-map>
</div>
` like this.
You can use 100vh instead of 100%
agm-map {
height: 100vh;
}
You can use height 100% if you have a parent div <div id="map"></div> contain agm-map and in your css file
#map {
height: 100vh;
}
agm-map {
height: 100%;
}
https://stackblitz.com/edit/angular-google-maps-demo-dzi5kg?file=app%2Fapp.component.css

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/

Dynamically updating css in Angular 2

Let's say I have an Angular2 Component
//home.component.ts
import { Component } from 'angular2/core';
#Component({
selector: "home",
templateUrl: "app/components/templates/home.component.html",
styleUrls: ["app/components/styles/home.component.css"]
})
export class HomeComponent {
public width: Number;
public height: Number;
}
The template html file for this component
//home.component.html
<div class="home-component">Some stuff in this div</div>
And finally the css file for this component
//home.component.css
.home-component{
background-color: red;
width: 50px;
height: 50px;
}
As you can see there are 2 properties in the class, width and height. I would like the css styles for width and height to match the values of the width and height properties and when the properties update, the width and height of the div update. What is the proper way to accomplish this?
Try this
<div class="home-component"
[style.width.px]="width"
[style.height.px]="height">Some stuff in this div</div>
[Updated]:
To set in % use
[style.height.%]="height">Some stuff in this div</div>
To use % instead of px or em with #Gaurav's answer, it's just
<div class="home-component" [style.width.%]="80" [style.height.%]="95">
Some stuff in this div</div>
This should do it:
<div class="home-component"
[style.width]="width + 'px'"
[style.height]="height + 'px'">Some stuff in this div</div>
You can also use hostbinding:
import { HostBinding } from '#angular/core';
export class HomeComponent {
#HostBinding('style.width') width: Number;
#HostBinding('style.height') height: Number;
}
Now when you change the width or height property from within the HomeComponent, this should affect the style attributes.
If you want to set width dynamically with variable than use [] braces instead {{}}:
<div [style.width.px]="[widthVal]" [style.height.px]="[heightVal]"></div>
<div [style.width.%]="[widthVal]" [style.height.%]="[heightVal]"></div>
The accepted answer is not incorrect.
For grouped styles one can also use the ngStyle directive.
<some-element [ngStyle]="{'font-style': styleExpression, 'font-weight': 12}">...</some-element>
The official docs are here
Check working Demo here
import {Component,bind} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
import {FORM_DIRECTIVES} from 'angular2/form';
import {Directive, ElementRef, Renderer, Input,ViewChild,AfterViewInit} from 'angular2/core';
#Component({
selector: 'my-app',
template: `
<style>
.myStyle{
width:200px;
height:100px;
border:1px solid;
margin-top:20px;
background:gray;
text-align:center;
}
</style>
<div [class.myStyle]="my" [style.background-color]="randomColor" [style.width]="width+'px'" [style.height]="height+'px'"> my width={{width}} & height={{height}}</div>
`,
directives: []
})
export class AppComponent {
my:boolean=true;
width:number=200px;
height:number=100px;
randomColor;
randomNumber;
intervalId;
textArray = [
'blue',
'green',
'yellow',
'orange',
'pink'
];
constructor()
{
this.start();
}
start()
{
this.randomNumber = Math.floor(Math.random()*this.textArray.length);
this.randomColor=this.textArray[this.randomNumber];
console.log('start' + this.randomNumber);
this.intervalId = setInterval(()=>{
this.width=this.width+20;
this.height=this.height+10;
console.log(this.width +" "+ this.height)
if(this.width==300)
{
this.stop();
}
}, 1000);
}
stop()
{
console.log('stop');
clearInterval(this.intervalId);
this.width=200;
this.height=100;
this.start();
}
}
bootstrap(AppComponent, []);
You can dynamically change the style(width and height) of div by attaching dynamic value to inline [style.width] and [style.hiegh] property of div.
In your case you can bind width and height property of HomeComponent class with the div's inline style width and height property like this...
As directed by Sasxa
<div class="home-component"
[style.width]="width + 'px'"
[style.height]="height + 'px'">Some stuff in this div
</div>
For the working demo take a look at this plunker(http://plnkr.co/edit/cUbbo2?p=preview)
//our root app component
import {Component} from 'angular2/core';
import {FORM_DIRECTIVES,FormBuilder,AbstractControl,ControlGroup,} from "angular2/common";
#Component({
selector: 'home',
providers: [],
template: `
<div class="home-component" [style.width]="width+'px'" [style.height]="height+'px'">Some this div</div>
<br/>
<form [ngFormModel]="testForm">
width:<input type="number" [ngFormControl]="txtWidth"/> <br>
Height:<input type="number"[ngFormControl]="txtHeight" />
</form>
`,
styles:[`
.home-component{
background-color: red;
width: 50px;
height: 50px;
}
`],
directives: [FORM_DIRECTIVES]
})
export class App {
testForm:ControlGroup;
public width: Number;
public height: Number;
public txtWidth:AbstractControl;
public txtHeight:AbstractControl;
constructor(private _fb:FormBuilder) {
this.testForm=_fb.group({
'txtWidth':['50'],
'txtHeight':['50']
});
this.txtWidth=this.testForm.controls['txtWidth'];
this.txtHeight=this.testForm.controls['txtHeight'];
this.txtWidth.valueChanges.subscribe(val=>this.width=val);
this.txtHeight.valueChanges.subscribe(val=>this.height =val);
}
}
All the above answers are great. But if you were trying to find a solution that won't change the html files below is helpful
ngAfterViewChecked(){
this.renderer.setElementStyle(targetItem.nativeElement, 'height', textHeight+"px");
}
You can import renderer from import {Renderer} from '#angular/core';
I liked the look of WenhaoWuI's idea above, but I needed to identify the div with class .ui-tree in the PrimeNG tree component to set the height dynamically.
All the answers I could find required the div to be named (ie #treediv) to enable the use of #ViewChild(), #ViewChildren(), #ContentChild(), #ContentChilden() etc. This was messy with a third party component.
I finally found a snippet from Günter Zöchbauer :
ngAfterViewInit() {
this.elRef.nativeElement.querySelector('.myClass');
}
This made it easy:
#Input() height: number;
treeheight: number = 400; //default value
constructor(private renderer: Renderer2, private elRef: ElementRef) { }
ngOnInit() {
this.loading = true;
if (this.height != null) {
this.treeheight = this.height;
}
}
ngAfterViewInit() {
this.renderer.setStyle(this.elRef.nativeElement.querySelector('.ui-tree'), 'height', this.treeheight + "px");
}
you can achive this by calling a function also
<div [style.width.px]="getCustomeWidth()"></div>
getCustomeWidth() {
//do what ever you want here
return customeWidth;
}
In Html:
<div [style.maxHeight]="maxHeightForScrollContainer + 'px'">
</div>
In Ts
this.maxHeightForScrollContainer = 200 //your custom maxheight
My solution was a combination of the #ViewChild() and ngAfterViewInit() function.
HTML:
<div
class="form-field text-form-field"
#textInputContainer
>
<label *ngIf="field?.label"> My Label </label>
<input type="text"/>
</div>
TS:
#ViewChild("textInputContainer") textInputContainer;
constructor() {}
ngOnInit(): void {}
ngAfterViewInit(): void {
this.textInputContainer.nativeElement.style.width = "50%";
}

Resources