Dynamic styling not working in Angular2 - css

Following is my working code, which is not giving any error in console and printing the array items and test heading as expected. BUT somehow dynamic background styling in not working, Let me know what I am doing wrong here.
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template: `
<h1>{{name}}</h1>
<div class="one" *ngFor="let item of colArr" style="background: {{item}};">{{item}}</div>
`,
styles: [`
.one {
width: 100%;
text-align: center;
padding: 10px;
margin: 5px;
}
`]
})
export class HomeComponent {
public name = 'test';
public colArr = ['#111111', '#222222', '#333333', '#444444', '#555555', '#666666', '#777777', '#888888', '#999999'];
}
Following is the output I am getting -

Direct binding to style is discouraged (doesn't work well on all browsers). Use instead
<div class="one" *ngFor="let item of colArr" [ngStyle]="{background: item}">{{item}}</div>
or
<div class="one" *ngFor="let item of colArr" [style.background]="item">{{item}}</div>

Related

How do we use the input:focus selector in angular 2+ component?

I have a form that contains something like the following:
<div class="form-field">
<input-component [tabIndex]="tabData.tabEnable"></input-component>
</div>
<div class="form-field">
<input [tabIndex]="tabData.tabEnable" matInput cgiPrecision type="number"/>
</div>
In the css I have this:
input:focus {
border: $border-width solid $darkblue
}
but the border only shows on the input element and not the input-component component which has an input wrapped inside of it. How can I get the input:focus to work for the custom angular component as well?
Your custom component should listen for the focus event, then focus the input.
#Component({
selector: 'custom-input',
template: `<input #myInput type="text" [(ngModel)]="innerValue">`,
styles: [`
input {border: 5px solid green; }
input:focus { border: 5px solid blue; }
`]
})
export class CustomInputComponent implements ControlValueAccessor {
#ViewChild('myInput', {static: false}) inputCtrl;
//...functions to implement ControlValueAccessor
#HostListener('focus')
focusHandler() {
this.inputCtrl.nativeElement.focus();
}
}
Here's a stackblitz demonstrating.
scss files are limited to their angular component. If you want to use css globally, use the style.scss.
Another option is, integrate the scss into your child component with the style-urls array:
#Component({
selector: 'input-component',
templateUrl: '/input-component.html',
styleUrls: [
'./input-component.scss', // own scss file
'./../path-to-other-compontent.scss' // <--- here
]
})
export class InputComponent {
[...]
}

Apply CSS styles on html tags after create them dynamically (inside .ts file)

I'm trying to add DIV after the project run (add it dynamically) but the problem is it didn't take the CSS style that I've set to it.
import { Component, OnInit, AfterViewInit } from '#angular/core';
#Component({
selector: 'app-chat2',
templateUrl: './chat2.component.html',
styleUrls: ['./chat2.component.css']
})
export class Chat2Component implements OnInit,AfterViewInit {
messages = [];
totalOnline = 0;
user = 1;
constructor() { }
ngOnInit() {
}
ngAfterViewInit(){
const divMessages: HTMLDivElement = document.querySelector(".msg_history");
let m = document.createElement("div");
m.innerHTML =
`<div class="incoming_msg">
<div class="incoming_msg_img" > <img src="https://ptetutorials.com/images/user-profile.png" alt="sunil"> </div>
<div class="received_msg">
<div class="received_withd_msg">
<p>Abdulaziz Burghal , Hello from Chat</p>
<span class="time_date"> 4:53 AM | June 9</span></div>
</div>
</div>`;
divMessages.appendChild(m);
divMessages.scrollTop = divMessages.scrollHeight;
}
}
Note: div that I've created it inside HTML file took the CSS style without any problem .
So, how could apply the CSS style on div's that I'll create them by code
Update:
Added CSS
.incoming_msg_img {
display: inline-block;
width: 6%;
}
.received_msg {
display: inline-block;
padding: 0 0 0 10px;
vertical-align: top;
width: 92%;
}
.received_withd_msg p {
background: #ebebeb none repeat scroll 0 0;
border-radius: 3px;
color: #646464;
font-size: 14px;
margin: 0;
padding: 5px 10px 5px 12px;
width: 100%;
}
Update 2
when I add the CSS styles as inline style it's work but the problem is the Div that contains the image it's CSS doesn't work!
You can apply the css in a few ways.
Via css
It's not clear why the css style isn't working, if you post it we can probably help more. Are you targeting the div or class of your dynamicly created html in the css?
Dynamically in JS
You'll have to get the element in JavaScript, either by using the m element you have or attaching a unique id to one of your elements.
const el = document.getElementById("${unique id})
Then you can set the style
el.style.cssText = "${your style text}"
If you use angular way to fill your list the CSS will work:
HTML
<div class="inbox_chat">
<div class="chat_list active_chat" *ngFor="let userData of listOfUsers">
<div class="chat_people">
<div class="chat_ib">
<h5>{{userData.userName}} <span class="chat_date">{{userData.creationDate}}</span></h5>
<p>{{userData.messageText}}</p>
</div>
</div>
</div>
</div>
TypeScript part:
listOfUsers: Array<InboxChatBoxDto> = [];// define it gloably
fillInboxChat(){
this._messageService
.inboxChat()
.pipe(
finalize(() => {
//alert("finished")
//finishedCallback();
})
)
.subscribe((result) => {
this.listOfUsers=result;
// });
});
}
If you use javascript to build your HTML you need to use an inline CSS property:
HTML part
<div class="inbox_chat"></div>
TypeScript part (use javascript code within it):
fillInboxChat(){
this._messageService
.inboxChat()
.pipe(
finalize(() => {
//alert("finished")
//finishedCallback();
})
)
.subscribe((result) => {
const divMessages: HTMLDivElement = document.querySelector(".inbox_chat");
result.forEach((item,index)=>{
let m = document.createElement("div");
m.className="chat_list"
m.style.cssText=` border-bottom: 1px solid #c4c4c4;
margin: 0;
padding: 18px 16px 10px;`
m.innerHTML = `<div class="chat_people" style='overflow:hidden; clear:both;' >
<div class="chat_ib" (click)="fillMessageHistory(`+item.userId+`)">
<h5 style='font-size:15px; color:#464646; margin:0 0 8px 0;'>` + item.userName +`<span class="chat_date" style='font-size:13px; float:right;'>`+ moment(item.creationTime ).format('YYYY/MM/ddd') +`</span></h5>
<p style='font-size:14px; color:#989898; margin:auto'>`+ item.messageText+`</p>
</div>
</div>`;
divMessages.appendChild(m);
});
});
}

ngbTooltipConfig tooltipClass not loading custom style tooltip

I am trying to add custom class to ngbTooltip which is working fine on ng-bootstrap official documentation
ngBootstrap Link
I am trying to replicate the same in my code:
tooltip-test.component.html
<div class="row mt-5 ml-5">
<div class="col">
<button type="button" class="btn btn-primary" ngbTooltip="Tool tip on top" placement="top"
tooltipClass="my-custom-class">Tooltip</button>
</div>
</div>
tooltip-test.component.ts
import { Component, OnInit, ViewEncapsulation } from '#angular/core';
import { NgbTooltipConfig } from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'app-tooltip-test',
templateUrl: './tooltip-test.component.html',
styleUrls: ['./tooltip-test.component.css'],
providers: [NgbTooltipConfig],
// encapsulation: ViewEncapsulation.None
})
export class TooltipTestComponent implements OnInit {
constructor(tooltipConfig: NgbTooltipConfig) {
tooltipConfig.openDelay = 500;
tooltipConfig.tooltipClass = 'my-custom-class'
}
ngOnInit() {
}
}
tooltip-test.component.css
.my-custom-class .tooltip-inner {
background-color: darkgreen;
font-size: 125%;
}
.my-custom-class .arrow::before {
border-top-color: darkgreen;
}
But I want to achieve same without using encapsulation: ViewEncapsulation.None or ::ng-deep or :host in my code.
tooltipConfig.openDelay = 500; is working fine but
tooltipConfig.tooltipClass = 'my-custom-class' is not loading class.
I even tried tooltipClass="my-custom-class" in HTML.
Can anyone tell me where I am going wrong?
Stackblitz Link where code is not working
All you need is to understand what is view encapsulation in Angular. Here is a good article: https://blog.thoughtram.io/angular/2015/06/29/shadow-dom-strategies-in-angular2.html

material angular select dropdown renders totally outside app-root

https://material.angular.io/components/select/overview
the select dropdown renders totally outside app-root.
Basically it creats a div with class="cdk-overlay-container" which is appended as sibling of the app. I want the drop down to open at exactly where I embed <mat-select> tag. What am I missing.
Here is my code
import { Component, Input, Output, OnInit, OnChanges, SimpleChanges, ChangeDetectionStrategy, EventEmitter } from '#angular/core';
import {FormControl} from '#angular/forms';
#Component({
selector: 'my-app',
template: `
<nav class="row navbar navbar-default navbar-fixed-top">
<div class="navbar-container">
<div class="navbar__content">
<mat-form-field>
<mat-select [formControl]="pc" panelClass="example-panel-{{pc.value}}">
<mat-option *ngFor="let panelColor of panelColors" [value]="panelColor.value">
{{ panelColor.viewValue }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</nav>
<div class="main-page">
NAVBAR ENDED MAIN PAGE STARTS
</div>
`,
styleUrls: [ './app.component.scss' ],
changeDetection: ChangeDetectionStrategy.Default
})
export class AppComponent {
private pc = new FormControl('red');
private panelColors = [
{value: 'red', viewValue: 'red'},
{value: 'blue', viewValue: 'blue'},
{value: 'green', viewValue: 'green'}
];
}
I created a stackblitz here
That's because you're missing a theme.
Add the following line to the top of your styles.scss or declare a theme (read the guide for more info):
#import '~#angular/material/prebuilt-themes/indigo-pink.css';
This can help you find the right path :
In the app.component.html, add a class to select <mat-form-field> tag :
<mat-form-field class="myForm">
At the bottom of app.component.scss
/*.navbar-default{
height: 120px;
}*/
.myForm {
height: 100px;
}
#cdk-overlay-2 > div {
margin-top: 80px;
}
.page-content {
margin-top: 100px;
}
.main-page{
height: 130px;
}
You have to import #import "~#angular/cdk/overlay-prebuilt.css"; in styles.scss.

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

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

Resources