Where to apply the parent theme class when using :host-context(.theme_name) in Angular2? - css

I'm building a themed Angular2 app. I have loads of nested components and I would like to change the theme for the whole app by changing one parent class. Let's say one theme is called "theme1". When I apply this to a very parent html-tag, all the nested child components will then switch style by using :host-context, like this:
:host-context(.theme1) .title-toc {
font-family: "bookmania";
font-weight: 700;
font-size: 20pt;
text-transform: uppercase;
color: #a5a5a5;
}
However, where to put this class="theme1"? When I put it to <body>, it worked so the code itself works, but I need to change the theme dynamically so it has to be inside some Angular component instead where I can use [ngClass]. For example inside AppComponent. But when I put it inside app.component (for example router-outlet or any other wrapping tag that should wrap my whole app), it didn't work anymore.
Do I have to make it deep with ::ng-deep somehow or what could be wrong?

You can bind to your root component element's class attribute like this:
export class AppComponent implements OnInit {
#HostBinding('attr.class') mainClass = 'theme1';
changeTheme(theme) {
this.mainClass = theme;
}
}

:host-context() sees the classes applied on the document body. You can set the class of body with JavaScript after the application has loaded, like this:
var myclass = "my-theme-name";
document.querySelector('body').classList.add(myclass);
This way you can load the theme name even from server and then apply it to the body from any Angular2 component via JS:
:host-context(.my-theme-name) .my-theme-specific-style

Related

Vaadin-flow: Css stylesheet import for custom components with shadow root element

I created a server-side component with a shadow-root element.. Is it possible to import a style sheet for the elements within that shadow-root? The CssImport annotation does not work, and I couldn't find anything similar, that could work?!
I could create a static String and add an element, but a css-file-import would be better?! (and of course I could use the component without a shadow-root, but the question was "is it possible" ... )
MyCustomComponent.java
#Tag("my-custom-component")
#CssImport("./components/my-custom-component.css")
public class MyCustomComponent extends Component {
public MyCustomComponent() {
super();
ShadowRoot shadow = getElement().attachShadow();
Span span = new Span();
span.getElement().setAttribute("part", "caption");
Div div = new Div();
div.getElement().setAttribute("part", "content");
shadow.appendChild(span.getElement());
shadow.appendChild(div.getElement());
}
}
my-custom-component.css
:host [part='caption'] {
background-color: red;
}
:host [part='content'] {
background-color: blue;
}
I'm curious why you would want a shadow root around a Flow component, as it doesn't really provide any benefits other than CSS encapsulation.
The #CssImport annotation with the themeFor parameter won't help you in this case, as that only works with Web Components using ThemableMixin (https://github.com/vaadin/vaadin-themable-mixin/).
I'm not sure whether it's possible to load css into a shadow root with Flow, but as long as you have part attributes on all elements you want to style, you can do that with a regular (non-shadow-dom) stylesheet, like so:
my-custom-component::part(caption) {
color: red;
}
Just put that in your styles.css or wherever you have your app's normal global css.

How to have different styles for common componnent instance in Angular?

I have a component called the amount component which is a shared library and I want to use that component in multiple places and I want to give that component different styles from where i use it. How to achieve it in angular ?
PS: amount component, needs styles for background, h2, button.
You can give custom styles to your account-component by adding an Input Attribute by using the #Input() Decorator & pass the styles or class name to that component depending upon where it is opened from.
Then you can use ngClass or ngStyle to apply those styles to your component.
For example in your account-component:
export class AccountComponent implements OnInit {
#Input() customClass: string;
}
Account Component HMTL
<div [ngClass]="customClass"> <h1>Account Component</h1> </div>
Account Component CSS
customClassRed:{
color: red;
}
customClassBlue:{
color: blue;
}
and in your components where you are opening account-component from just pass the class name (if you use the class name, then you need that class with styles in your components.css as I did above) or the styles depending upon your preferences
Another Component
<account-component [customClass]="customClassBlue"> </account-component>

Why is IntroJS tooltipClass option not working

I'm using introJS in my angular application. I went step by step based on the tutorial on their site. I wanted to change the styling so I basically copied their code but it didn't work. It added the class but it has no effect on the tip.
My TS:
this.introJS.setOptions({
tooltipClass: 'customTooltip'
}).start();
My Scss:
.customTooltip * {
color: #e81717;
font-size: 18px;
}
.customTooltip .introjs-tooltip-title {
color: #0a41c9;
}
My html:
<div class="card-demo" data-tooltipClass="customTooltip" data-title="Welcome!" data-intro="Hello World!">
</div>
The problem was that the class was created in components scss. But I needed to create a global css class and use that.
Why? Because the components is nested in app-root and app-root is a sibling to the intro.js elements but they are both in the index.html so when I created the global css class intro.js elements were able to access it.

How to apply a CSS style dynamically using React JS?

I would like to know how to apply CSS dynamically to all the elements in a page that belong to a CSS class in React JS?
Currently I am using the following:
document.querySelectorAll('.my-paragraph-class').forEach(function (x: any) {
x.style.fontSize = `${data.value}%`;
});
It works but I would like to know if there is a more efficient way instead of using document.querySelectorAll?
Also when the page loads new text, document.querySelectorAll has to be called again after the text loads, which is not ideal. I would like to know how to persist the modified CSS changes when new text is loaded dynamically?
Thank you in advance
For applying a static font size to a class you shouldn’t have to use JavaScript at all.
In your css file just do:
.my-paragraph-class: {
font-size: 10rem || whatever;
}
To dynamically add styling you could use a CSS in JS tool like styled components. For styled components you would import styled components and then write a code outside of your react function like this:
const StyledParagraph = styled.p`
font-size: 10rem || ${props => props.fontSize}
`
In your JSX you would do something like:
<StyledParagraph fontSize=“10rem”> Filler Text </StyledParagraph>

Applying dynamic styling to injected HTML in Angular 2

For an Angular project I'm working on, I'm injecting HTML into a <div> like so:
<div class="myClass" [innerHTML]="htmlToInsert"></div>
The htmlToInsert contains a variety of things, notably <a> tags. Previously we were styling all these tags like so:
.myClass ::ng-deep a {
color: #f00;
text-decoration: none;
}
And this worked fine. But now I need the color of these links to be dynamically generated during component initialization, based on data coming in from elsewhere. All of the dynamic styling I've seen in Angular requires you to apply things directly to the HTML tag, but we don't have them here to work with.
How can I apply dynamic styling to HTML that is also dynamically generated? Can I directly change the CSS class somehow? Would using a pipe be the correct approach here? Is there another method I don't know about? I could maybe refactor code if there is absolutely no other way of doing this.
So if you can't modify the innerHTML you are passing in, you can achieve this functionality with a custom directive. Essentially you would tag your div that contains your innerHTML with a custom directive. That directive then looks for any anchor tags in it and changes the color based on an input.
// component.html
<div anchorColor [color]="dynamicColor" [innerHTML]="htmlToInsert"></div>
// directive.ts
#Directive({selector: '[anchorColor]'})
export class AnchorColorDirective implements OnAfterViewInit {
#Input() color: string;
constructor(private el: ElementRef){
}
// afterViewInit lifecycle hook runs after DOM is rendered
ngAfterViewInit(){
// get anchor element
let anchorEl = this.el.nativeElement.querySelector('a');
// assign color
if(anchorEl){
anchorEl.style.color = this.color;
}
}
}
Here is a working plunkr https://plnkr.co/edit/QSYWSeJaoUflP94Cy4Hm?p=preview

Resources