import additional scss as theme on demand in angular - css

I am implementing admin panel for my application and the same has been lazy loaded, but I would like to speparate scss for admin panel. Say:
Public Portal
ecom-blue.scss
Admin Panel:
ecom-blue.scss
ecom-admin.scss
As of now I am importing both the CSSs in theme.scss like this way:
#import '~#angular/material/theming';
#include mat-core();
#import "themes/ecom-blue";
#import 'themes/ecom-admin';
$background: map-get($ecom-theme, background);
$foreground: map-get($ecom-theme, foreground);
which is further imported in app.scss this way:
#import "scss/variables";
#import "scss/themes";
#import "scss/views";
In angular.json
"styles": ["src/assets/styles/app.scss",
"node_modules/font-awesome/css/font-awesome.css"]
The problem with this approach is that the style.css (compiled file) will be having both the themes whereas I just want rent of the css to be included where my admin router layout is activated as per lazy loading.
may I know the best approach for this so that style.css file should be divided as per module and also to be loaded when required.
Edit:
This is how my router component look like:
#Component({
selector: 'app-auth-layout',
templateUrl: './auth-layout.component.html',
styleUrls: ['./../admin-layout.scss'],
// encapsulation: ViewEncapsulation.None
})
and this is how it is lazy loaded:
{
path: '',
component: AuthLayoutComponent,
children: [
{
path: 'admin4556',
loadChildren: () => import('./views/admin/admin.module').then(m => m.AdminModule),
data: { title: 'Admin', breadcrumb: 'Admin'}
}
]
},

UPDATE: If you will use ViewEncapsulation.None, yes, this allows you to apply base styles for children components, for example, if you style tag <p> in the parent component, the same style for <p> will be applied in the children component. BUT this is not the best practice. So if you sometimes will want to change your style in the child you need to add !important or add more points to your element to make it more specific. Will be better if you move out all common styles to BaseTheme or even styles.scss, and leave some specific styles inside lazy-loaded components. '' helps if you want to split your routes by different style areas if you have only one area base style you can go with styles.css only.
ORIGINAL:
If you want to apply some common style, for example, to user and admin components, and at the same time have some styles lazy-loaded specifically to each of them, you can do it with '' route. This is not some specific route, it's just skipped and goes further to children, but this allows us to add additional styles before it. It looks like this:
{
path: '',
component: BaseTheme, //base style
children: [
{ path: 'adminpanel', loadChildren: () => import('./adminpanel/adminpanel.module').then(m => m.AdminPanelModule) } //inside we add specific style
{ path: 'userpanel', loadChildren: () => import('./userpanel/userpanel.module').then(m => m.UserPanelModule) } //inside we add specific style
]
}

Related

Can I load into an array all the CSS classes into an array listed in the styleUrls property of an Angular Component

In my Angular component I wish to load one of the CSS files used in my app so I can collect the contained CSS classes, put them into an array and loop through them in my component's HTML template. I know from previous experience that in JavaScript/TypeScript I can load all of my CSS stylesheets into JavaScript/TypeScript like so:
Array.prototype.forEach.call(document.styleSheets, (styleSheetList: any) => {
console.log(styleSheetList.cssRules); // do something
});
This is okay but a little inefficient and I shouldn't really call "document" in my Angular component file as I have heard this is considered an anti-pattern. So could I add the specific CSS file to/through my component's styleUrls property then somehow expose it in my component and loop through the classes there?
Something like this:
#Component({
selector: 'css-list',
templateUrl: './css-list.component.html',
styleUrls: ['./css-listcomponent.scss', 'the-file-i-want-to-iterate-through.css']
})
export class CssListComponent implements OnInit {
// so let's load the style sheet
ngOnInit() {
Array.prototype.forEach.call(this.styleUrls[1].cssRules, (cssRules: any) => {
console.log(cssRules); // do something
});
}
}

dynamic switching of two styles.css file in one angular application

I have to merge two angular applications into one major angular application. Hence, now i am having two styles.css files in one angular application. On running this application after merging both, css is going completely for the angular application.
Is there any way by which we can call this two style.css files dynamically depending on the requirement? Or I need to check each class one by one?
I recommend you to use two different layouts, each one is a component, so each one has a different set of styles. That it's really easy wit angular router.
In your routing module:
// Layout 1
{
path: '',
component: Layout1Component,
children: [
{ path: 'pageL1_1', component: PageL1_1Component },
{ path: 'pageL1_2', component: PageL1_2Component }
]
},
// Layout 2 routes goes here here
{
path: '',
component: Layout2Component,
children: [
{ path: 'pageL2_1', component: PageL2_1Component },
{ path: 'pageL2_2', component: PageL2_2Component }
]
},
In your app.component.html:
<router-outlet></router-outlet>
The layouts templates has to include the element to in order to show child navigation componets.
IMPORTANT: Each layput controller should disable view encapsulation so styles applies ti child components:
#Component({
selector: 'app-layout_1',
templateUrl: './layout_1.component.html',
styleUrls: ['./layout_1.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class Layout1Component implements OnInit {
...
}

How to share LESS or CSS files in Angular 7 application?

On the src root of an Angular 7 application I have 3 less files:
styles.less (global styles)
constants.less (less constants like colors, fonts, ...)
reset.less (css reset)
And I have the following on angular.json under build:
"styles": [
"src/resets.less",
"src/constants.less",
"src/styles.less"
]
In styles.less, to use constants, I needed to add the following:
#import (reference) 'constants.less';
The problem is how to use the constants inside a component's less files?
As an example let me show a HomeComponent (home.component.ts):
import { Component } from '#angular/core';
#Component({
selector: 'home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.less']
})
export class HomeComponent {
}
To use the constants.less I need to add to home.component.less the following:
#import (reference) './../../constants.less';
This makes it work but I have a few questions:
Can I reference constants.less somehow without './../..'?
Should I load constants.less in HomeComponent styleUrls?
Should I move constants.less to a shared folder instead of having in src root?
I placed it there because styles.less is in src root and is using it.
So I though I needed to load it using the angular.json definition file.

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.

How to apply styles to component-B from component-A stylesheet in Angular-Cli without making styles apply globally?

I have two Angular components:
#Component({
selector: ‘component-a’,
templateUrl: './component-a.html',
styleUrls: [ ‘./component-a.scss' ],
})
#Component({
selector: ‘component-b’,
templateUrl: './component-b.html',
styleUrls: [ ‘./component-b.scss' ],
})
In component-a HTML:
<div class=“cmp-a-container”>
component A
<component-b></component-b>
</div>
and in component-b HTML:
<div class=“cmp-b-container”>
component B
</div>
component-b is reused inside other components. But when component-b is used inside component-a I want it to have a set of specific styles applied on the .cmp-b-container class.
If I add the following code into component-a.scss,
.cmp-a-container {
.cmp-b-container { /* Styles here */ }
}
The styles won’t apply. I believe this is how Angular works.
So my solution to this is, adding the styles on the styles.scss (the global sass file).
Is this the right way to do this or is there a way to apply styles specified in component-a’s stylesheet to component-b’s inner html when it’s wrapped by component-a?. Why has Angular not made this possible?
I'm using Angular-Cli and Sass.
you should use ::ng-deep so that your styles propagates to child components, see https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep
It should go something like this:
.cmp-a-container ::ng-deep{
.cmp-b-container { /* Styles here */ }
}

Resources