referencing css in angular - css

I working in an Angular 2 application. I'm very new to Angular. I'm wondering why my CSS is not working.
I have three files:
landing.component.html
landing.component.scss
landing.component.ts
landing.component.html looks like this:
<div class="c-nav__left">
<img src="/public/imgs/logo#2x.png" width="145px" height="64px" />
<span class="_navbarLogoText">Risk Alive</span>
</div>
Welcome to the landing page!
There's a couple style class I'm referencing there: c-nav__left and _navbarLogoText.
Now here's landing.component.scss:
#import "../../../scss/base.scss";
#import "../../../scss/navbar.style.scss";
All that landing.component.scss does is import other scss files from elsewhere in the application. The class seen in landing.component.html are in navbar.style.scss.
Then there's landing.component.ts:
import { Cookie } from 'ng2-cookies/ng2-cookies';
import { Component } from '#angular/core';
import { ModalService } from '../../../app/common/services/modal.service';
import { Subscription } from 'rxjs/Subscription';
#Component({
templateUrl: './landing.component.html',
styles: [require('./landing.component.scss'), require('../../../scss/navbar.style.scss') ],
providers: [ ModalService ],
})
export class LandingComponent {
....
}
As you can see, I'm requiring both landing.component.scss and navbar.style.scss.
Yes, navbar.style.scss is being referenced twice. I'm trying both approaches: referencing it by an import statement in the scss files itself and also by a require statement in the typescript file.
But neither of these work. I do not see my styles on the page.
Can anyone suggest what I'm doing wrong? Thank you.

You shouldn't use require in the styles param to the #Component decorator - instead use styleUrls:
styleUrls: ['./landing.component.scss']

Related

Why would a CSS file be imported into typescript?

In an older, complex code base that uses Angular 4 with a custom Webpack, there were some components that imported a css file, in the same way that you would import a module for a side effect. An example (this is the complete file, with different variable names):
import { Component, OnInit } from '#angular/core';
import '../../assets/css/styles.css';
#Component({
selector: 'sidebar-app',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.css']
})
export class SidebarComponent implements OnInit {
ngOnInit() {
}
}
styles.css
.content_body {
padding: 0;
}
.basic_page_wrapper {
padding: 0;
}
I have never seen css being imported in typescript, and all other examples I've found use the styles in some way, for example
import * as s from './Button.css';
Why would a css file be imported like import '../../assets/css/styles.css'; inside an angular component?
When using bundlers such as webpack or browserify, one might import a CSS file in order to process it and pack it into the same bundle as the JavaScript module that imports it.
In webpack, this is done using the style-loader. Read more in this medium post!

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.

Broken leaflet map with Angular-CLI and yaga. Where to insert leaflet.css?

I'm trying to display a simple leaflet-map by using the yaga component (npm yaga-module). Therefore I generated a new project with angular cli and followed the introduction on the npm page. In the end, I got a broken map.
Image of the broken map.
I already implemented a working map with the leaflet library + JS and even with yaga in the ionic framework. In both cases I get the same broken map, if I remove the link to the leaflet.css. But where do I have to link the css file? If I insert the path in my .angular-cli.json, it seems to be loaded successfully. But then my map disappears completely.
Did I make a mistake? You can find my code below:
app.module.ts:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { YagaModule } from '#yaga/leaflet-ng2';
import { AppComponent } from './app.component';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
YagaModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.ts:
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'Test';
}
app.component.html:
<h1>{{title}}</h1>
<yaga-map [zoom]="2">
<yaga-tile-layer [url]="'http://a.tile.osm.org/{z}/{x}/{y}.png'"></yaga-tile-layer>
</yaga-map>
My app.component.css file is empty. Any ideas what's going wrong?
In your styles.css add the following line of code
#import '../node_modules/leaflet/dist/leaflet.css'
This question was discussed in the YAGA leaflet-ng2 github repository. We think that the leaflet.css was missing or that there wasn't set a height on the map. Without setting the height the map has a height of 0px, so that it seems like the map disappeared. Have a look on issue 286 in the leaflet-ng2 github repository. If you still have the problem, please write us on github.
In Ionic2 you have to add the leaflet.css in your app.scss like that:
#import "node_modules/leaflet/dist/leaflet";

Dynamic styleUrls in angular 2?

Is it possible to dynamically inject urls to stylesheets into a component?
Something like:
styleUrls: [
'stylesheet1.css',
this.additionalUrls
]
or (wishful thinking and note that this is just fake code):
export class MyComponent implements dynamicUrls {
ngDynamicUrls() {
this.inject(['anotherStylesheet.css', 'anotherStylesheet2.css']);
}
}
Because if you're gonna be able to override certain styles from stylesheet1 without having access to it, how are you supposed to do that? My only idea is to have dynamic styleUrls somehow but I don't think this is even possible from what I could find.
Any ideas?
It's possible in some maybe hack way it worked for me. You can manipulate Angular 2 Component decorator, create your own and return Angular's decorator with your properties.
import { Component } from '#angular/core';
export interface IComponent {
selector: string;
template?: string;
templateUrl?: string;
styles?: string[];
styleUrls?: string[];
directives?: any;
providers?: any;
encapsulation?: number;
}
export function CustomComponent( properties: IComponent): Function {
let aditionalStyles: string;
try {
aditionalStyles = require(`path to aditional styles/${ properties.selector }/style/${ properties.selector }.${ GAME }.scss`);
properties.styles.push(aditionalStyles);
} catch (err) {
console.warn(err)
}
}
return Component( properties );
}
And in your component replace default angular 2 #Component with new one.
import { CustomComponent } from 'path to CustomComponent';
#CustomComponent({
selector: 'home',
templateUrl: './template/home.template.html',
styleUrls: [ './style/home.style.scss']
})
export class ......
I have found a solution:
1. I have changed the styleurls to styles in the component decorator.
2. I will get my variable.
3. I will use the require command in my decorator.
import { Component } from '#angular/core';
import { environment } from '../environments/environment';
let lang = environment['lang'];
#Component({
selector: 'app',
templateUrl: './app.component.html',
styles: [require('./app.component.css'), require('./app.component.' + lang + '.css')]
})
export class AppComponent {
constructor() { }
}
In this basic example I have imported the environment variable and changed the css string dynamically.
I used to have the same need to dynamically inject urls to stylesheets and eventually ended to initialize a component for each variable css (in my case 3 differents styles) with empty template and use them in my app component with ngIf condition.
Thanks to the use of property "encapsulation: ViewEncapsulation.None", the style of the selected component is then added to the header of the page and enable to get the correct renderer for the whole page.
I don't think you can have dynamic stylesheet URLs, because you cannot access your class property or method inside #Component decorator.
But you can achieve your goal by having dynamic style classes in your template.
I used the stylesheet link in the html template with ngIf condition, it worked for me.
<link rel='stylesheet' href="/stylesheets/classicTheme.css" *ngIf="theme === 'classic' " />
<link rel='stylesheet' href="/stylesheets/styleTheme.css" *ngIf="theme === 'style' " />

Resources