Writing css for Angular 2 View encapsulation via styleUrl - css

I am making a simple hello world app (currently migrating from angular 1) I used angular-cli to generate my components and it created a stylesheet and linked it in my component via styleUrls. None of my styles apply the way I think they are supposed to unless I do "viewEncapsulation.none." Is there something I'm missing? Or is there a better way to write out css for this?
If I use the default encapsulation ( ViewEncapsulation.Emulated or even native) my styles don't show up at all.
import { Component, OnInit } from '#angular/core';
import { ViewEncapsulation } from '#angular/core';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
encapsulation: ViewEncapsulation.None,
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
My CSS looks like this:
.app-header{
display: block;
opacity:0.2;
}

You need to use this css:
:host() {
display: block;
opacity:0.2;
}

Don't manipulate the component tag, this tag scope belongs to the parent component who uses it. manipulate only tags inside your html template component.

I think you need to set module:module.id in the component declaration for angular to search for the file in the right location. Have you verified that the CSS gets loaded in the non working case?
I am assuming you are using the app-header css somewhere in header.component.html? Try the below code.
import { Component, OnInit } from '#angular/core';
import { ViewEncapsulation } from '#angular/core';
#Component({
module: module.id,
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
constructor() { }
ngOnInit() { }
}

Related

Angular How to load css from server

I want to try to load css from a server/external source intro angular. I'm trying to use the DomSanitizer already but without succes. The stylesheet is shown inside the network tab of chrome but the html does not apply the stylesheet.
chrome networktab:
Inside the TS file:
import {Component, OnInit, ViewEncapsulation} from '#angular/core';
import {DomSanitizer} from "#angular/platform-browser";
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
encapsulation: ViewEncapsulation.None,
})
export class AppComponent implements OnInit{
title = 'angulardynamicss';
cssUrl = 'http://localhost:8080/api/csspoc/asFile'
constructor(public sanitizer: DomSanitizer) {}
ngOnInit(): void {}
}
And HTML looks like:
<link rel="stylesheet" [href]='sanitizer.bypassSecurityTrustResourceUrl("http://localhost:8080/api/csspoc/asFile")'>
<p class="test">hello</p>
The stylesheet file contains:
.test {
background-color: blue;
}
p{
color:yellow;
}
Why do you inject it in the AppComponent? Can you not just add the <link> tag in the <head> of your index.html?

kendo-card tag not formatting a card on angular app

Looking for help to troubleshoot this.
When I try to create a card on the UI using kendo, it works on stackblitz:
https://stackblitz.com/edit/5zvomp--run?file=app/app.component.ts
but when trying to create in my angular app, it doesnt show up properly. There are no errors in the console and import { LayoutModule } from '#progress/kendo-angular-layout'; is also there.
html template:
<kendo-card class="user-card">
<kendo-card-header class="k-hbox">
<div>
<h1 kendoCardTitle>Turtle</h1>
<p kendoCardSubtitle>Turtle is a small animal</p>
</div>
</kendo-card-header>
</kendo-card>
angular component:
import { Component, OnInit, Input } from '#angular/core';
import * as faEllipsisH from '#fortawesome/pro-regular-svg-icons/faEllipsisH';
#Component({
selector: 'user-card',
templateUrl: './user-card.component.html',
styleUrls: ['./user-card.component.css']
})
export class UserCardComponent implements OnInit {
#Input() public card: any;
public faEllipsisH = faEllipsisH;
public constructor() { }
public ngOnInit(): void {
}
}
The only way that I was able to replicate this was if you did not import the Kendo-UI stylesheet.
Take a look at this example: https://stackblitz.com/edit/angular-pnudiu?file=index.html
If you uncomment out the commented line in index.html, you get the properly styled card. For more information on how to include the styling and themes, visit this documentation: https://www.telerik.com/kendo-angular-ui/components/styling/#toc-including-themes-by-using-precompiled-css

Angular Dynamic Components - Add Class and other attributes

I am using the following code for creating the dynamic components
import {
Component, OnInit, ViewContainerRef, ViewChild, ViewChildren,
ReflectiveInjector, ComponentFactoryResolver, ViewEncapsulation, QueryList, Input, AfterViewInit
} from '#angular/core';
import { Router, ActivatedRoute } from '#angular/router';
import { forEach } from '#angular/router/src/utils/collection';
import { IComponent } from 'app/app.icomponent';
#Component({
encapsulation: ViewEncapsulation.None,
selector: 'dynamic-component',
entryComponents: [HomeComponent, HighlevelSignalComponent],
template: `
<div #dynamicDiv [ngClass]="classFromMenu" >
<ng-template #dynamicComponentContainer></ng-template>
</div>
`,
styleUrls: [
'./dynamic-content.component.css'
],
})
export class DynamicComponent implements IComponent, OnInit, AfterViewInit {
classFromMenu: any;
#ViewChild('dynamicComponentContainer', { read: ViewContainerRef }) dynamicComponentContainer: ViewContainerRef;
constructor(private resolver: ComponentFactoryResolver, private route: Router,
private activatedRoute: ActivatedRoute, ) {
}
.......
buildComponent(passedData) {
// orderAndObjs has the data for creating the component
this.orderAndObjs.forEach(obj => {
var componentFactory = this.resolver.resolveComponentFactory(obj.component);
var compRef = this.dynamicComponentContainer.createComponent(componentFactory);
// compRef is the component that is created.
//Assuming the component that i am trying to create is <dynamic-component>.
//I want to add either a class or any other attribute like this
//<dynamic-component class="flex">
});
}
}
}
The dynamic-component is created perfectly fine and everything is working as expected. But the only issue is I want to add a class for dynamic-component so that it can be
<dynamic-component class="dynamicClass">
Any help is appreciated :(
Hmm.. I usually add it to the selector of component that is supposed to be an entryComponent ...
selector: 'dynamic-component.someclass',
^^^^^^^^^^^
to add attribute use attribute selector:
selector: 'dynamic-component[myattr=value]',
I call it hidden feature of entryComponents
but its declarative approach and can't be changed at runtime(indeed we can change it)
In Angular 5/6, using Renderer2 from #angular/core, you can do something like below:
constructor(private resolver: ComponentFactoryResolver, private route: Router,
private activatedRoute: ActivatedRoute, private renderer2: Renderer2) {
}
buildComponent(passedData) {
this.orderAndObjs.forEach(obj => {
var componentFactory = this.resolver.resolveComponentFactory(obj.component);
var compRef = this.dynamicComponentContainer.createComponent(componentFactory);
this.renderer2.addClass(compRef.location.nativeElement, 'flex');
});
}
High-level DOM operations are performed with Renderer2 provider. Considering that it was injected, it is:
this.renderer2.addClass(compRef.location.nativeElement, 'dynamicClass');
It should be noticed that depending on how dynamic element is attached to DOM, this may be unnecessary complication.
Considering that dynamicComponentContainer is real DOM element and not <ng-template>, the view of dynamic component can be directly mounted to the container, thus eliminating <dynamic-component> wrapper element:
Given the container:
<div class="dynamicClass" #dynamicComponentContainer></div>
It will be:
var compRef = componentFactory.create(
this.injector,
[],
this.dynamicComponentContainer.element.nativeElement
);

Angular Universal CSS imports not working

I'm just testing out how Angular Universal handles the imports of third party JavaScript and CSS libraries. For ease of use I tried with jQuery and Bootstrap.
I'm using the Universal Starter repo https://github.com/angular/universal-starter and installed jQuery and Bootstrap through npm.
In my app.component.ts I included jQuery like so and it works perfectly.
import { isBrowser, isNode } from 'angular2-universal'
var jQuery: any = require('jquery');
...
#Component({
changeDetection: ChangeDetectionStrategy.Default,
encapsulation: ViewEncapsulation.Emulated,
selector: 'app',
templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
title = 'ftw';
ngOnInit(): void {
if (isBrowser) {
jQuery('#universal').css({'color': '#FF0000', 'font-size': '25px'})
}
}
}
Though when I want to import a css file it won't work properly. I'm importing it within my app/client.ts file as follows.
...
// Angular 2
import { enableProdMode } from '#angular/core';
import { platformUniversalDynamic } from 'angular2-universal/browser';
import { bootloader } from '#angularclass/bootloader';
import { load as loadWebFont } from 'webfontloader';
import 'bootstrap/dist/css/bootstrap.css';
// enable prod for faster renders
enableProdMode();
...
The actual Bootstrap css is within my Webpack bundle but my HTML isn't styled in any way. Anybody had a similar problem with this and knows how to fix this issue?
In order to make import 'bootstrap/dist/css/bootstrap.css'; work, you'll need style loader, which is not installed with universal-starter repo. Sidenote: If you use bootstrap.css as is, and you want to use universal-starter, you can copy bootstrap.min.css into assets folder and add a link tag for it in index.html.
Go to the angular-cli.json or angular.json file at the root of your Angular CLI project folder, and find the scripts: [] property, and include the path to jQuery as follows:
"scripts": [ "../node_modules/jquery/dist/jquery.min.js",
"../node_modules/bootstrap/dist/js/bootstrap.js"]
Now, to use jQuery, all you have to do is to import it in whatever component you want to use jQuery.
import * as $ from 'jquery';
(or)
declare var $: any;
import { Component, OnInit } from '#angular/core';
import * as $ from 'jquery';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
ngOnInit()
{
$(document).ready(function(){
// your code
});
}
}

Angular 2 external style doesn't get inlined to header

I have this component definition in typescript:
import {Component, ViewEncapsulation} from 'angular2/core';
#Component({
selector: 'my-app',
templateUrl: '/views/sandbox.html',
styleUrls: ['/styles/sandbox.css'],
styles: [`.wow { background-color: red; }`],
encapsulation: ViewEncapsulation.Emulated
})
export class SandBox { }
According to this article: http://blog.thoughtram.io/angular/2015/06/25/styling-angular-2-components.html
both the style in the styles section and in the external stylesheet should be inlined into the header by angular.
Unfortunately, the second does not get injected, angular injects only the one in the styles section.
I have tried accessing /styles/sandbox.css from browser, it is fine. Angular is also able to access /views/sandbox.html so i have no idea why it is not happening.
I am using: "angular2": "2.0.0-beta.2" (latest beta AFAIK)
I made some tests and strangely styles from the sandbox.css only applies if you use a relative paths within the styleUrls attribute:
#Component({
selector: 'my-app',
templateUrl: '/views/sandbox.html',
styleUrls: ['../styles/sandbox.css'],
styles: [`.wow { background-color: red; }`],
encapsulation: ViewEncapsulation.Emulated
})
export class AppComponent {
constructor() {
}
}
Edit
After having a look at the source code, Angular2 prevents from using absolute path for the styleUrls. See this line:
https://github.com/angular/angular/blob/master/modules/angular2/src/compiler/style_url_resolver.ts#L12
export function isStyleUrlResolvable(url: string): boolean {
if (isBlank(url) || url.length === 0 || url[0] == '/') return false; // <-----
var schemeMatch = RegExpWrapper.firstMatch(_urlWithSchemaRe, url);
return isBlank(schemeMatch) || schemeMatch[1] == 'package' || schemeMatch[1] == 'asset';
}
Hope it helps you,
Thierry
The Best way to fix this is use another css file for your component and add it to your StyleUrls list. Cleaner and will scale as you components grow.
You can use systemjs and commonjs module dependencies loader, to load templates, styles and other files.
in commonjs moduleId : module.id
in systemJs __moduleName
import {Component} from '#angular/core';
#Component({
moduleId:module.id,
selector: "exf-header",
templateUrl: "header.html",
styleUrls:['header.css']
})
export class HeaderComponent {
}

Resources