ionic 5 component selector is not applied to html element - css

I have an ionic 5 app for which I built each page using the cmd line, so they were created using the correct structure.
However, when I try to run it, the page styles aren't used, even though the browser shows the css file has been loaded.
I have the following in the .ts page:
#Component({
selector: 'app-onboard',
templateUrl: './onboard.page.html',
styleUrls: ['./onboard.page.scss'],
})
The html file:
<body>
<app-onboard>
...lots of other elements
<div class="style1">
</div>
</app-onboard>
</body>
The scss file:
app-onboard {
.style1 {
color: #ff00ff;
}
}
style1 is on an html element, but it is not applied. However, when I delete the app-onboard wrapper, the style is applied i.e.:
.style1 {
color: #ff00ff;
}
Why would the presence of the app-onboard selector prevent the styles from being applied in the page?

There should be a . in front of the app-onboard in the scss file as you're calling the scss class instead of the html tag like so
.app-onboard {
.style1 {
color: #ff00ff;
}
}
Hence the reason why the style only applied once you removed it.
If you wish to use the selector as per your current scss you'll have to change your html file to
<body>
<app-onboard>
...lots of other elements
<div class="style1">
</div>
</app-onboard>
</body>
I'm assuming the html file is outside of the app-onboard component and you're calling the component from it.

Related

why moving class to shared css file in Angular increases bundle size

This is for an Angular 11 application. I have a shared css file I'm including in several components as follows:
#Component({
selector: 'app-my-x-selector',
templateUrl: './my-component-x.html',
styleUrls: ['component-x.css', 'shared.css']
})
Adding the following test class to one of the components' css file increases
the bundle size by by 61 bytes, which matches the size of the added source snippet. But moving the class to the shared css increases the bundle size by 140 bytes. Why? It seems like Angular effectively clones the class for each component that includes the shared css file which imho severly limits, if not defeats the purpose of having shared css.
.tr-test00 {
display: block;
margin-left: 45rem;
padding-left: 3rem;
}
#Ya, Imagine you has simple two components with a .css like
//component-one
template: `<h1>Hello</h1>`,
styles: [`h1 { color:blue }`]
//component-two
template: `<h1>By</h1>`,
styles: [`h1 { color:red }`]
Angular make an unique bundle similar to
h1[_ngcontent-edf-c40] {
color: green;
}
h1[_ngcontent-edf-c41] {
color: red;
}
And create an .html like
<hello _ngcontent-bwn-c39="">
<h1 _ngcontent-edf-c40="">Hello</h1> //<--this is the component one
</hello>
<other_ngcontent-bwn-c42="">
<h1 _ngcontent-edf-c41="">By</h1> //<--this is the component two
</other>
This makes that in component-one you see the h1 green and in component-two h1 red
When you refered a common .css to two differents components, Angular makes a bundle like
h1[_ngcontent-edf-c40] {
color: green;
}
h1[_ngcontent-edf-c41] {
color: green;
}
And again the .html is
<hello _ngcontent-bwn-c39>
<h1 _ngcontent-edf-c40>Hello</h1> //<--this is the component one
</hello>
<other _ngcontent-bwn-c48>
<h1 _ngcontent-edf-c41>By</h1> //<--this is the component two
</other>
This is the reason because the bunlde increase two times. If you want, you can take another aproach that is use a common .css and add in your angular.json in the way
.common h1{
color:green
}
And enclosed yours component in a div
<div class="common">
<h1>Hello</h1>
</div>
<div class="common">
<h1>By</h1>
</div>
The .html it's looks like
<hello _ngcontent-jxl-c46="">
<div class="common">
<h1>Hello</h1>
</div>
</hello>
<other _ngcontent-jxl-c46="">
<div class="common">
<h1>By</h1>
</div>
</other>

Cannot Understand the Use of :host in components in Angular2

What i have understood of host is that if i have a child component inside a parent component and we want to style a child component from the parent component we can use :host .
and :host-context for vice-versa.
Please let me know if this is the right use of host .
https://angular.io/docs/ts/latest/guide/component-styles.html
When i try to do the same in my App it dosent work
App component template
<div class ="top">
<h1>
Home Component
</h1>
<hr>
<app-ngrx></app-ngrx>
<router-outlet></router-outlet>
<div>
ngrx component template
<h3 class="mine">NGRX</h3>
<button (click)="increment()">Increment</button>
<div>Current Count: {{ counter | async }}</div>
<button (click)="decrement()">Decrement</button>
<button (click)="reset()">Reset Counter</button>
App component CSS
:host(.mine){
color:red;
}
This do not Seem to work Please help i am not able to understand.
I looked at this question But just not able to figure out
Angular 2: How to style host element of the component?
Updated after #Gunter Answer
In my app-ngrx template i have added
<h3 class = "mine">NGRX</h3>
<button (click)="increment()">Increment</button>
<div>Current Count: {{ counter | async }}</div>
<button (click)="decrement()">Decrement</button>
<button (click)="reset()">Reset Counter</button>
and in the app-ngrx css file i have added
:host(.mine){
color:red;
}
But even without adding mine in app component like
<app-ngrx></app-ngrx>
The h3 is red where as i feel it should be red when <app-ngrx class = "mine"></app-ngrx>
What i have understood of host is that if i have a child component
inside a parent component and we want to style a child component from
the parent component we can use :host . and :host-context for
vice-versa
No, this is not what it used for.
:host selector comes from shadow DOM spec.
...This scoped subtree is called a shadow tree. The element it's
attached to is its shadow host.
In angular world, a component's template is a shadow tree. The component's element is a shadow host. So when you're defining styles for :host selector, the styles are applied to the component's element.
:host
In your example, if you defined styles in my-app component, the styles will be applied to <my-app> DOM element. This particular configuration:
:host(.mine){
color:red;
}
Will be applied to the host element that has .mine class:
<my-app class="active">
If you defined styles in app-ngrx component, the styles will be applied to <app-ngrx> DOM element, NOT <my-app>. This particular configuration:
:host(.mine){
color:red;
}
Will be applied to the host element that has .mine class:
<app-ngrx class="active">
:host-context
Now, :host-context is also applied to the host element, but the function (parenthesis) takes a selector that is checked not against the host element itself, but against all ancestors up to document root. If such element is found, the styles are applied.
For example, this selector
:host(.mine){
color:red;
}
matches such structure:
<my-app class="mine">
whereas, this selector:
:host-context(.mine){
color:red;
}
matches this structure:
<div class="mine">
...
<my-app>
This is useful, if you want to apply styles to components view (shadow root) conditionally. This makes h2 always bold:
h2 {
font-weight: bold;
}
whereas this
:host-context(.make-inner-components-bold) h2 {
font-weight: bold;
}
makes them bold only if your component is inside an element with class .make-inner-components-bold.
:host { ... } selects the component itself
:host(.mine) { ... } selects the component itself when it has class="mine" set
:host-context(.mine) { ... } selects the component itself when one of its ancestors has class="mine" set
See also https://angular.io/docs/ts/latest/guide/component-styles.html
#Component({
selector: 'h3',
styles: [':host(.mine) { color: red; }],
template: '<ng-content></ng-content>'})
class MyH3Component{}
<h3 class="mine">this is red</h3>
<h3>this is black</h3>
or with :host-context
#Component({
selector: 'h3',
styles: [':host-context(.mine) { color: red; }],
template: '<ng-content></ng-content>'})
class MyH3Component{}
<body class="mine">
<my-app><my-app>
<body>
AppComponent
template: '<h3>this is red</h3>'
or with class="mine" set
<body>
<my-app><my-app>
<body>
AppComponent
template: '<h3>this is black</h3>'
update
If you want to style the content of a child component (instead of the child component itself) you can use /deep/
:host child /deep/ h3 {
color: red;
}
update 2
::slotted is now supported by all new browsers and can be used with `ViewEncapsulation.ShadowDom
https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted

Overriding the encapsulated :host-style of external component

Is it possible to override :host-styling of an external angular2-component?
We're making a library including a sidebar-component. This component has a default (fallback) background, but this should be overridable by css/theme used in the app.
#Component({
selector: 'sidebar',
styles: [`
:host { background-color: green; }
`],
template: `
<h1>sidebar</h1>
<ng-content></ng-content>
`
})
export class SideBarComponent { .... }
Main App css:
<style>
sidebar {background: red; color: yellow; }
</style>
This returns a sidebar with green background and yellow text, but I want a red background...
Edited:
As found on http://blog.angular-university.io/how-to-create-an-angular-2-library-and-how-to-consume-it-jspm-vs-webpack/: add an attribute to the body-tag:
<body override>
<app></app>
</body>
And in your css: use a selector for this attribute:
[override] hello-world h1 {
color:red;
}
This way, your css does not have to be parsed.
Previous solution:
I've found a solution myself: instead of linking my (theming) css-file in index.html, which isn't parsed, I imported this particular css-file in the app.component.ts annotation.
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet/css" type="text/css" href="/assets/style/app.css" />
</head>
<body>
<app></app>
</body>
</html>
app.component.ts:
import { ... }
#Component({
selector: 'app',
styles: [`
#import "assets/style/theme.css";
`],
template: `
...`,
})
export class AppComponent {...}
theme.css:
sidebar {background: red; }
Its not possible to overwrite styles set in a component's styles this way. See point 3 on the "Using Component Styles" section in the Component Styles docs (https://angular.io/docs/ts/latest/guide/component-styles.html)
Our component's styles cannot be changed by changes to styles
elsewhere in the application.
Using :host-context is probably a nicer way to acheive this (although i have never tried myself).
You should try to check the same with host-context. As per documentation host-context works just like the function form of :host(). It looks for a CSS class in any ancestor of the component host element, all the way up to the document root. It's useful when combined with another selector.
In the following example, we apply a background-color style to all <h2> elements inside the component, only if some ancestor element has the CSS class theme-light.
:host-context(.theme-light) h2 {
background-color: #eef;
}

How to use component variable within css / style tag in Angular 2?

How can I use component variables within style TAG in Angular 2?
I do have an Angular 2 component for my header which I like to color depending on a users setting. Thus I'd like to assign an background and font color. While I know how to to this with an attribute binding to an element, I couldn't figure out how to use in a style tag.
Using attribute binding for style works well, however this gets pretty anoying for several subelements, especially if they are nested within other sub components. [ngStyle]= attribute is also only working on a single element.
<header id="header" [style.background-color]="changeBackground()">
<div>
Some Text
Some Link
<subcomponent></subcomponent>
</div>
<div> ... a lot mor stuff </div>
</header>
Thus I'd like to add something like
<style>
#header, #header a {
color: {{mycolor}};
}
</style>
to the html template. However this is not working
Similar Questions do not answer this question yet and only show attribute binding as a solution:
Angular2 dynamic change CSS property
Dynamically updating css in Angular 2
https://scotch.io/tutorials/all-the-ways-to-add-css-to-angular-2-components
https://coryrylan.com/blog/introduction-to-angular-2-ngclass-and-ngstyle
It looks to me like you are just creating a new component called 'subcomponent', why not do that?
subcomponent.ts:
import { Component } from '#angular/core';
#Component({
selector: 'subcomponent',
templateUrl: './subcomponent.html',
})
export class SubComponent {
mycolor = 'blue';
}
subcomponent.html:
<style>
#header, #header a {
color: {{mycolor}};
}
</style>
To your #Component object, add
styles:[ `#header, #header a {
color: {{mycolor}};
}`]
So for example:
#Component({
template: `<header id="header" [style.background-color]="changeBackground()">
<div>
Some Text
Some Link
<subcomponent></subcomponent>
</div>
<div> ... a lot mor stuff </div>
</header>`,
styles: [ `#header, #header a {
color: {{mycolor}};
}`
`]
})
Use NgStyle as explained in this answer
https://stackoverflow.com/a/41903349
in short
<header id="header" [ngStyle]="getStyle()">
<div>
Some Text
Some Link
<subcomponent></subcomponent>
</div>
<div> ... a lot mor stuff </div>
</header>
and
getStyle(): any {
return {"background-color" : this.changeBackgroundColor()};
}

Polymer deep CSS

I am building a Polymer Single Page Interface with a lot of custom elements.
Now I want my elements to have some sort of master style, which I can define in the index.html or my main content element. Think of it like this:
index.html
<style>
.classWhichWillBeUsedInCustomElements {
mainColor: #e0e0e0;
}
</style>
or
<script>
mainColor = "#e0e0e0";
</script>
my-cool-element.html
<polymer-element name="my-cool-element">
<template>
<paper-button style="color: {{mainColor}}"></paper-button>
</template>
</polymer-element>
or
<polymer-element name="my-cool-element">
<template>
<style>
.coolButton {
width: 300px;
color: {{mainColor}};
}
</style>
<paper-button class="coolButton"></paper-button>
</template>
</polymer-element>
Except that this doesn't work.
I have tried:
Creating a global variable window.defaultColor and using it like color: {{defaultColor}};
Using core-style in a parent element, without much luck
Creating a css class in my index.html and calling it in a custom element
What is the right way to achieve this? I am trying to avoid using Less
Use the following pattern in the index.html or a global stylesheet:
<style>
body /deep/ .classWhichWillBeUsedInCustomElements {
mainColor: #e0e0e0;
}
</style>
Then you could use the class within the custom element. The global style will punch the shadow boundary. You could replace body with any other element or selector under which you want to punch the shadow dom boundary.
More on deep here: https://www.polymer-project.org/0.5/articles/styling-elements.html#cat

Resources