How to use SASS for components style in Angular 2? - css

In Angular 2 when we define a component we can specify a styleUrls property to the decorator which points to a set of stylesheets to be applied to the component:
#Component({
selector: 'the-app'
templateUrl: 'templateFile.html',
styleUrls: ['componentStyles.css', 'moreComponentStyles.css']
})
export class TheAppComponent {}
Now, what if I want to write these styles with SASS?
I know I would need to use Gulp or Grunt to transpile the SCSS stylesheets to plain CSS. But this makes me confused on how we would correctly point Angular to the correct stylesheets.
How could I organize this workflow of using SASS with Gulp/Grunt together with Angular 2? How to use SASS to write the Angular 2 components styles?

After following this wiki, I got some Error: Uncaught (in promise): Expected 'styles' to be an array of strings which I resolved using this answer.
Final solution is here:
home.component.ts:
import { Component } from '#angular/core';
#Component({
selector: 'home',
template: require('./home.component.html'),
styles: [ String(require('./home.component.scss')) ]
})
export class HomeComponent { }
webpack.conf.js: (part of it)
{
test: /\.(css|scss)$/,
loaders: [
'style',
'css',
'sass',
'postcss'
]
},

You can use .scss in Component like this-
styles: [require('normalize.css'), require('./app.scss')],
See if this helps.

I'm using it this way:
import {Component} from "#angular/core";
// for webpack
require('./footer.scss');
#Component({
selector: 'footer',
templateUrl: 'app/footer/footer.html',
styleUrls: ['app/footer/footer.scss'],
})
export class FooterComponent {}

Command line inside project folder where your existing package.json is: npm install node-sass sass-loader raw-loader --save-dev
In webpack.common.js, search for "rules:" and add this object to the end of the rules array (don't forget to add a comma to the end of the previous object):
{
test: /\.scss$/,
exclude: /node_modules/,
loaders: ['raw-loader', 'sass-loader'] // sass-loader not scss-loader
}
Then in your component:
#Component({
styleUrls: ['./filename.scss'],
})

Related

Storybook LESS imports included globally. How to separate styles per story?

On my storybook site, I have added Less imports to some of my components, but the CSS files generated by webpack are included globally in the of the site for all components. From the storybook documentation, it seems like CSS should be isolated to each component by default, so I'm not sure what the issue is. Any suggestions on how to isolate styles per component/story?
Ver: Storybook 6.2.9
Main.js (less-loader):
config.module.rules.push({
test: /\.less$/,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
lessOptions: {
paths: [path.resolve(__dirname, "node_modules")],
},
sourceMap: true,
webpackImporter: false,
}
}]
});
stories/component.stories.js:
import React from 'react';
import { Component } from './component.js';
import './component.less';
import '#package/index.less';
...
stories/component-2.stories.js:
import React from 'react';
import { Component2 } from './component2.js';
import './component2.less';
import '#package-2/index.less';
...
This results in all LESS files being converted to CSS and added to the section of the site. They do not load separately per story.
If I missed any info, please lmk. Thanks :)

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.

Move css to an external file in an angular 4 component using webpack

This is the error I'm getting:
Error: Expected 'styles' to be an array of strings.
even though I've specified the styles in an array of strings:
styleUrls: ['./app.component.css']
Here is the relevant code, any ideas what I'm doing wrong?
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template: `<h2 class="float-left">Hey</h2>`,
styleUrls: ['./app.component.css']
})
export class AppComponent { }
app.component.css
.float-left {
float: left;
}
Snippet from webpack.common.js
module: {
rules: [{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
{
test: /\.html$/,
loader: 'html-loader'
},
{
test: /\.css$/,
loader: 'css-loader'
}]
},
As I have not personally experienced this - I did find a closed thread (but with some recent additions, nonetheless) - that may help you with your issue.
https://github.com/webpack-contrib/style-loader/issues/123
The first suggested, and apparently working at the time, solution that sticks out to me is this one:
{ test: /\.css$/, loaders: ['to-string-loader', 'css-loader'] }
There are other suggestions and solutions listed further down; hopefully one of those will help you resolve your problem.
One thing to note - it seems it may/may not make a difference if you're using angular-cli. If you are, then make sure you're following their guidelines with using webpack, as they have a couple small differences, as opposed to using a non-angular-cli build.
You need to use style-loader after css-loader.
test: /\.css$/,
use: [{loader: 'style-loader'},{loader: 'css-loader'}]
The loaders in the "use" array are run in order from the last in the array to first in the array. First the css-loader is run to prepare the CSS, then the result is passed to the style-loader to embed the styles in the page.

Angular2: How to import a stylesheet from node_modules?

Question: In my Angular2 (4.0) app, how can I import stylesheets (css) from a module in node_modules?
I have a module located here:
node_modules/#swimlane/ngx-datatable
I want to import this stylesheet:
node_modules/#swimlane/ngx-datatable/release/index.css
I've tried the following approaches, with no luck:
In my components own scss file:
#import '~#swimlane/ngx-datatable/release/index.css';
In my component:
#Component({
encapsulation: ViewEncapsulation.None,
selector: 'site_table',
template: require('./site_table.html'),
styleUrls: ['./site_table.scss', '#swimlane/ngx-datatable/release/index.css']
})
Because you're already using SCSS, in your ./site_table.scss import it like so
#import "~swimlane/ngx-datatable/release/index";
Note: do not add the extension.
It will import stylesheet from node package. That served my well, hope it will do for you too. That way you just have to use single stylesheet in your component and it will look cleaner.
If you are using new the angular-cli with the angular.json file and not webpack, the tilde (~) in #sickelap's answer probably doesn't work for you.
Instead what you can do is add this in your angular.json file:-
...
"styles": [
...
],
"stylePreprocessorOptions": {
"includePaths": [
"node_modules/#swimlane"
]
},
...
Then, in your component's .scss file, insert this:
#import "ngx-datatable/release/index";
Note that the .css extension is not required.
Try it with a complete relative url:
#Component({
encapsulation: ViewEncapsulation.None,
selector: 'site_table',
template: require('./site_table.html'),
styleUrls: [
'./site_table.scss',
'../../node_modules/#swimlane/ngx-datatable/release/index.css'
]
})
Didn't tried your notation but node package resolution might not work without webpack. I may be wrong though.

How to bundle Angular 2 component css?

In my application for angular 1 I used to bundle all of the css in library.css and application.css. While this can be done with angular 2 the same way for ordinary css, there is a new feature that allows a "component css". As far as I can see Angular just downloads the css file and then processes it to add some id's to not interfere with each other.
Now if I just bundle all of these css'es Angular just won't be able to find them. Is it possible at all to do bundling of component css? Perhaps a similar way to bundling HTML exists, where HTML is really put into .js as string?
I managed to achieve this with webpack and a special angular2-template-loader plugin. This is the config from webpack 2:
module: {
rules: [
{
test: /\.ts$/,
use: ['awesome-typescript-loader', 'angular2-template-loader']
}
Basically what it does, it replaces templateUrl and styleUrls with inline template and styles and just stores them in a string as a separate "module".
How does it work
The angular2-template-loader searches for templateUrl and styleUrls
declarations inside of the Angular 2 Component metadata and replaces
the paths with the corresponding require statement. If keepUrl=true is
added to the loader's query string, templateUrl and styleUrls will not
be replaced by template and style respectively so you can use a loader
like file-loader.
The generated require statements will be handled by the given loader
for .html and .js files.
P.S. The whole set up can be found in Anagular tutorial.
These are the combination of the loaders that does the trick if you have
templateUrls and styleUrls
loaders: [{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
{
test: /\.html$/,
loader: 'raw-loader',
exclude: [root('src/index.html')]
},
{
test: /\.css$/,
loader: 'to-string-loader!css-loader'
}
],
and in the code
#Component({
selector: 'my-app',
templateUrl: 'sub.component.html',
styleUrls: ['app.component.css']
})
export class AppComponent {
}

Resources