Conditional stylesheet on Angular Component? - html

I have a situation where I have to component that are almost identical, except on 1 variable in the stylesheet. So let's say I have component1's css:
.selector {
background-color: 'red';
margin: 12px;
}
And component2's css:
.selector {
background-color: 'red';
}
Suppose HTML on both component is the same, as well as the .ts code.
However, there's a ng-content in each and the Is there a way to add the margin: 12px is important for component2.
Is there a way, in the component declaration, to have a conditional style, or even stylesheet (in a case where's there's more change than margin: 12px, but everything else is the same) ?

Have you thought about inheritance? Maybe Component2 could extend Component1 but reference a different styleUrl. This way Component2 would have all the logic and variables contained in Component1
#Component({
selector: "app-component-2",
templateUrl: "./component1.html",
styleUrls: ["./component2.css"]
})
export class Component2 extends Component1 {}

Related

How to add SCSS to a component of an angular library

I've created a library in angular 6. The problem is that styling is not applied. Here is my code:
mycustom.component.html
<div class="cutom-div">
Hello
</div>
mycustom.component.ts
import { Component, OnInit } from "#angular/core";
#Component({
selector: "lib-mycustom",
templateUrl: "./mycustom.component.html",
styleUrls: ["./mycustom.component.scss"],
})
export class MycustomComponent implements OnInit {
constructor() {}
ngOnInit() {}
}
mycustom.component.scss
.custom-div {
background: red;
height: 20px;
}
This was supposed to be simple. But there's no styling applied. I inspected the element also:
What else I'm missing out here. Please point out my mistake.
I'm building the library normally:
ng build my-library and then cd dist\my-library>npm pack
https://angular.io/api/core/ViewEncapsulation#None
None means that Angular does no view encapsulation. Angular adds the CSS to the global styles. The scoping rules, isolations, and protections discussed earlier don't apply. This mode is essentially the same as pasting the component's styles into the HTML.
#Component({
selector: "lib-mycustom",
templateUrl: "./mycustom.component.html",
styleUrls: ["./mycustom.component.scss"],
encapsulation: ViewEncapsulation.None, // <- This need use for global style
})

Styles are not getting applied to HTML injected via network call

In my angular 8.1.3 application, I am injecting HTML div, I want to apply styles to the classes used in that HTML payload.
But styles are not getting applied unless I put them in root level CSS of the project. (Which I dont want to do)
Sub-component.html
<div id="ImgBlock" class="col-xs-12">
<div> [innerHTML]="ImagePayload"></div>
</div>
here is my Sub-component.ts
#Component({
selector: 'SubComponent',
templateUrl: './SubComponent.html',
styleUrls: ['./SubComponent.scss'],
encapsulation: ViewEncapsulation.None
})
export class SubComponent implements OnInit, AfterViewInit {
public ImagePayload: string;
// Constructros and other functions
}
here is the parent component which creates an instance of sub-component and injects HTML payload in ImagePayload variable.
#Component({
selector: 'parentComponent',
templateUrl: './parentComponent.html',
styleUrls: ['./parentComponent.scss'],
encapsulation: ViewEncapsulation.None
})
export class parentComponent implements OnInit, OnDestroy {
showImage(data: Somedata) {
const dialog: DialogRef = this.dialogService.open({
title: 'recognise Image data ',
content: SubComponent,
});
const info = dialog.content.instance;
info.ImagePayload = data.challenge;
}
}
Here is a css style for class used in imagePayload variable.
input.Image_selection_checkbox {
width: 15px;
}
I applied the same style to
1) SubComponent.scss
2) parentComponent.scss
3) app.component.scss
(of parentCompoent)
4) style.scss of this particular sub-project
(Project have multiple sub-project as well)
but none of them are getting applied !
But when I put the same style in root style.scss (of the main project directory!)
It is getting applied.
I am having a limited idea about role of encapsulation. Is that a culprit?
what are the other issues?

Can I change a style of multiple components with one toggle

I am trying to achieve day/night feature with a click of a toggle on my web app.
I know how to add it to a single component with my nav menu lets say,
but I need to add it to multiple components.
One of the solutions I found is to use ng-deep but it feels a bit wrong to do it that way in the main CSS.
Another solution I have figured out is to create a service and subscribe to the toggle in each of the components, but again that feels like an overkill.
My questions is: Can I change a style of multiple components with one toggle?
Would prefer not to use JS.
Currently, my app.component looks like this
import { Component, ElementRef } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.less']
})
export class AppComponent {
title = 'Optimus Engine';
version = 'Latest';
day = true;
constructor(private element: ElementRef) {
}
dayNight() {
if (!this.day) {
this.element.nativeElement.classList.add('night');
}
if (this.day) {
this.element.nativeElement.classList.remove('night');
}
this.day = !this.day;
//BTW for some reason it does not remove the class but that's a different problem.
}
}
And then on my template:
<div class="toggle-box" (click)="dayNight()">
<input type="checkbox" name="checkbox1" id="toggle-box-checkbox" />
<label for="toggle-box-checkbox" class="toggle-box-label-left"></label>
<label for="toggle-box-checkbox" class="toggle-box-label"></label>
</div>
And then in less:
:host.night h1 {
transition: all 1s;
color: aliceblue;
}
But this works only for h1 and I'm wondering how to got other components to change with that toggle.
You can use a service to propagate a value accross multiple components.
For instance, a service like this:
export class ThemeService {
private modeSubject: BehaviorSubject<'day'|'night'> = new BehaviorSubject<'day'|'night'>('day');
public get mode():Observable<'day'|'night'>{
return this.modeSubject.asObservable();
}
public switchMode(newMode:'day'|'night'):void{
this.modeSubject.next(newMode);
}
}
And then, in your component, simply subscribe to the mode observable:
...
...
constructor(themeService: ThemeService){
themeService.mode.subscribe(mode => this.theme = mode);
}
...
...
finally, use [ngClass] to bind the theme to your template:
Any component implementing this logic will switch with your theme mode (day or night).
Keep in mind that I used two strings here but you can use an enum for sure, these were just for the example.

Computationally bind styles in Angular

Using Angular5 - I know how it is possible to bind an HTML element's style to a Boolean value, but I can't find an explanation to do this for multiple styles at the same time.
ie. I have found something like this works fine:
[style.background]="r.favourite === true ? '#3f51b5' : 'white'"
However I am also wanting to change the color of my text to white at this point also... And I don't want to clutter my components with lots of [style.xxx] tags.
Is there a way I can dynamically bind to a CSS class to apply when r.favourite === true?
I have seen ways in which this can be done... However this assumes you are binding within the same file as such:
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template: `
<button class="my-btn" [class.extraclass]="someProperty">Call to Action</button>
`,
styles: [`
.my-btn { font-size:1.7em; }
.extraclass { background: black; color: white; }
`]
})
export class AppComponent {
someProperty = true;
}
However my CSS is being stored in a shared file - such that I have a file structure like:
import { Component } from '#angular/core';
#Component({
selector: 'my-component',
styleUrls: ['./css/shared-styles.css']
template: `
<button class="my-btn" [class.extraclass]="someProperty">Call to Action</button>
`
})
export class MyComponent {
someProperty = true;
}
You can use NgClass.
<div [ngClass]="{'text-success':r.favourite ,'text-danger':!r.favourite}">
Where 'text-success' and 'text-danger' are classes you define.
Please refer to this great article about NgClass and NgStyle:
https://codecraft.tv/courses/angular/built-in-directives/ngstyle-and-ngclass/
Hope this helps

How can I separate CSS of two separate components in Angular 2?

In Component 1
CSS--
ngx-dnd-container {
color:black;
background-color: white;
}
HTML-
<ngx-dnd-container
[model]="targetItemsA"
dropZone="multiple-target-a"
</ngx-dnd-container>
In Component 2
CSS--
ngx-dnd-container {
color:white;
background-color: orange;
}
<ngx-dnd-container
[model]="targetItemsA"
dropZone="multiple-target-a"
</ngx-dnd-container>
Whenever I run my project in both component's html it is showing CSS of First Component. Please He
When defining an Angular Component, you can specify CSS stylesheets that will be used only by the Component, like so:
import { Component } from '#angular/core';
#Component({
selector: 'app-my-component',
templateUrl: 'my.component.html',
styleUrls: ['my.component.scss'] // <-- Here
})
export class MyComponent {
// Component code
}
Take note that the value is an Array and that it can thus take several file paths.