Implementing theme in angular2 - css

I am trying to implement theming in Angular2 project.
When someone change theme of web app, it will change the class of body using javascript. And each component in an application has relevant colors for each theme.
Can someone suggest me how to do this in Angular2 components.
when I write my component stylesheet with
body.theme-1 .header {
background-color: red;
}
it doesn't work.
Any other way to implement this.
If I cut same css from component stylesheet and put in to index.html or common stylesheet, it works. But it is a huge application and I don't want to write all component styles in to once place. Not manageable.

If you declare ViewEncapsulation.none in your component the styles from that component will apply globally to your application.
import { Component, ViewEncapsulation } from '#angular/core';
#Component({
selector: 'style-test',
template: `<div> Global stylesheet</div>`,
styles: ['body {
background: blue;
}'],
encapsulation: ViewEncapsulation.None // Use to
//disable CSS
//Encapsulation
//for this component
})
export class SecondComponent {
constructor() { }
}

I found answer from Angular2 documentation.
You can use :host-context() function
:host-context(.theme-1) .header {
background-color: red;
}
It works like a charm.
https://angular.io/docs/ts/latest/guide/component-styles.html
Check above link for further information

Related

Styling all Components Angular from styles.scss

Is it possible to define a style in e.g. the styles.scss that applies to all Components selectors
( app-componentA, app-componentB ...) ?
I know I could add the style to each selector individually but I'm worried that it will be forgotten in the future when a new component is added...
In short, I don't want to duplicate the code every time.
Any ideas?
EDIT:
I'm looking for a "css-query" which addresses all Angular components. So some kind of wildcard like
styles.scss
.app* {
margin-left: 20px; // will be applied to all DOM elements starting with app
}
In Your component
#Component({
selector: 'compA',
templateUrl: './compA.component.html',
styleUrls: ['./compA.component.css'],
encapsulation: ViewEncapsulation.None
})
try without incapsulation:
#Component({encapsulation: ViewEncapsulation.None})
OR turn off encapsulation globally
OR add some class for all components like compA & compB
OR in style.scss write compA, compB { /* some stiles */ }

Can we use different CSS language/pre processors for different components in a Angular Project

Suppose their are three Developers working on a same angular Project, each one of them is developing a different component, but during the initialization 'scss' is set as preferred styling language, but now one developer want to use stylus instead of 'scss' but the others are comfortable with 'scss'.
So is it possible to use different style language for different components in a angular project.
This will work. You can use sass/scss, less and stylus.
Just use the style preprocessor you want for the component you're working on. An example:
less-example.component.ts
#Component({
selector: 'less-example',
styleUrls: [
'./less-example.less'
],
templateUrl: './less-example.component.html'
})
export class LessExample {
}
less-example.less
#color: yellow;
h1 {
color: #color;
}
scss-example.component.ts
import {Component} from '#angular/core';
#Component({
selector: 'scss-example',
templateUrl: './scss-example.component.html',
styleUrls: [
'./scss-example.scss'
]
})
export class ScssExample {
}
scss-example.scss
$color: green;
h1 {
color: $color;
}
You can see this in action here
Yes you can generate component options
you can do so by add --styleext=[file extension] like so ng g c test --styleext=scss you can do that for each component you generate just specify --styleext option with pre-processor you want to use.

Angular 6 not applying scss styles

I have a component page and corresponding style sheet, however the classes in the component.scss dosen't apply to the page. There are no errors, I am still wondering why?
This is my product-detailpage.component.html
<div>
<h1>Product Detail Page</h1>
</div>
This is the .ts file
import { Component, OnInit } from '#angular/core';
import {ActivatedRoute} from '#angular/router';
import {ProductdetailService} from '../productdetail.service';
#Component({
selector: 'app-product-detailpage',
templateUrl: './product-detailpage.component.html',
styleUrls: ['./product-detailpage.component.scss']
})
export class ProductDetailpageComponent implements OnInit {
constructor(private route: ActivatedRoute, private productData: ProductdetailService) {
this.route.params.subscribe(params => console.log(params));
}
ngOnInit() {
}
}
This is the .scss file
body{color:Red !important}
app-product-detailpage{
h1{color:red !important}
}
However one thing I noticed was if I make changes to the global styles.css it works fine. just to check I changed the body color to green and it works.
My angular app is configured to work with scss. what could be the reason? can some one suggest?
Your SCSS won't work for your HTML file product-detailpage.component.html.
The reason is Angular uses shadow DOM for components. That means the tags <body> and <app-product-detailpage> are nowhere to be found in your component.
As per the documentation, The style specified in the component can only be applied to its template, which excludes the component.
This is the reason why your styles are not working on the component from component's style.scss but are working fine from global style sheet.
One way of doing it is to use :host pseudo selector as per this documentation which allows to add styles on the container in which component is placed.
The documentation says -
The :host selector is the only way to target the host element. You can't reach the host element from inside the component with other selectors because it's not part of the component's own template. The host element is in a parent component's template.
Because default css encapsulation in Angular is Emulated(ViewEncapsulation.Emulated) so Angular will render out like below:
input[_ngcontent-c0] {
border-radius: 5px;
}
So if you want set style to the currently component, you can use Native option.
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
encapsulation : ViewEncapsulation.Native
})
It will render like as:
input {
border-radius: 5px;
}
But finally I suggest you use global scss file to define style of <web component>.

Angular 4 - Not use styles from angular-cli.json

I have an angular 4 application where I have the global styles and scripts in angular-cli.json. Then I worked separately on the Landing page. After I turn the landing page into an angular component, I add all its styles in angular-cli.json as well. And now my landing page's bootstrap conflicts with global bootstrap in node_modules and my application breaks.
Currently angular-cli.json looks like this:
"styles": [
"../node_modules/bootstrap/dist/css/bootstrap.min.css",
"./dist/css/landing/bootstrap.min.css",
"./dist/css/landing/font-awesome.min.css",
"styles.css",
"./dist/css/AdminLTE.min.css",
"./dist/css/skins/_all-skins.min.css",
"../node_modules/froala-editor/css/froala_editor.pkgd.min.css",
"../node_modules/froala-editor/css/froala_style.min.css"
],
This is in landing.component.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-landing',
templateUrl: './landing.component.html',
styleUrls: ['./landing.component.css']
})
export class LandingComponent implements OnInit {
constructor() { }
ngOnInit() { }
}
I am almost missing my deadline, I can not resolve the conflicts between two huge css files. I was wondering if I could keep my Landing Page styles separated from application styles. Any help will be largely appreciated. Thank you.
You could try encapsulate your landing page as follows.
ViewEncapsulation.Native will wrap your component and its styles within a shadow root. Change your component style file to scss and import those styles in component style file and delete them from .angular-cli.json.
#Component({
selector: 'app-landing',
templateUrl: './landing.component.html',
styleUrls: ['./landing.component.scss'],
encapsulation: ViewEncapsulation.Native
})
export class LandingComponent implements OnInit {
constructor() { }
ngOnInit() { }
}
landing.component.scss
#import '<path-to-dist>/dist/css/landing/bootstrap.min.css';
#import '<path-to-dist>/dist/css/landing/font-awesome.min.css';
When you inspect DOM, you'll see app-landing as encapsulated.
Edit
Alternatively, you can use ViewEncapsulation.Emulated which is default (you do not have to set it within metadata). What this will do is to create custom attributes with all the styles and add those attributes to your markup as well. Shadow DOM may not be supported in some browsers. Try both and if Emulated works for you, use that.

Way to add custom class when using ngx-bootstrap modalService

When looking to the ngx-bootstrap source code here:
modal-options.class.ts
There is an optional class property defined as class?: string;.
What is the way to use it ?
Is it possible to add a custom class like:
this.modalService.config.class = 'myClass';
Before using the servive as for example:
this.modalRef = this.modalService.show(template, {
animated: false
});
This way, I think we can add custom CSS to the displayed modal
I've tried to add a custom class without success.
That class property is not an array, if applicable, does it mean that we can only add one custom class ?
Demo: by adding and overriding the modal class, the modal is not showing
https://stackblitz.com/edit/ngx-bootstrap-3auk5l?file=app%2Fapp.component.ts
Adding the modal class this way do not help:
this.modalRef = this.modalService.show(template, Object.assign({},
this.config, { class: 'gray modal-lg modal' }));
https://stackblitz.com/edit/ngx-bootstrap-awmkrc?file=app%2Fapp.component.ts
According to the ngx-bootstrap documentation about the Modal component (see the component tab), you can add a class member to the config object.
Important: Since the modal element is outside of the component element in the rendered HTML, the CSS encapsulation should be turned off for the component, or the style attributes for the class should be specified in another file, to make sure that the styles are applied to the modal element.
The code snippet below can be executed in this stackblitz.
import { Component, TemplateRef, ViewEncapsulation } from '#angular/core';
import { BsModalService, BsModalRef } from 'ngx-bootstrap';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
modalRef: BsModalRef;
config = {
animated: true,
keyboard: true,
backdrop: true,
ignoreBackdropClick: false,
class: "my-modal"
};
constructor(private modalService: BsModalService) { }
openModal(template: TemplateRef<any>) {
this.modalRef = this.modalService.show(template, this.config);
}
}
with a CSS file like this:
.my-modal {
border: solid 4px blue;
}
.my-modal .modal-header {
background-color: lime;
}
.my-modal .modal-body {
background-color: orange;
}
Update: This other stackblitz shows an example of CSS styles imported from an external file into styles.css, allowing to keep the CSS encapsulation in the component.

Resources