For the website Angular 8, Typescript and SCSS are used.
To display a map mgl-map is used.
Now i wanted to create a custom control for it and apply custom styles to it.
I add it to the map using:
const centerOnCoordinatesControl = new CenterOnCoordinatesControl();
this.mapBoxMap.addControl(centerOnCoordinatesControl, 'bottom-left');
which works fine but my custom styles don't get applied to the custom control.
To check if the css styles get loaded at all i created the same element outside the map control:
location.component.html:
<mgl-map class="mapbox-map"
[style]="defaultStyle"
[zoom]="zoom"
[center]="grazCoord"
(click)="onMapClick($event)"
(load)="mapLoaded($event)">
<mgl-control mglScale unit="metric" position="bottom-right"></mgl-control>
<mgl-control *ngIf="this.mapBoxMap" mglFullscreen position="top-right"></mgl-control>
<mgl-control *ngIf="this.mapBoxMap" mglGeolocate position="top-right"></mgl-control>
</mgl-map>
location.component.ts:
CustomControl:
class CenterOnCoordinatesControl {
private map: any;
private container: HTMLDivElement;
onAdd(map) {
this.map = map;
this.container = document.createElement('div');
const control = document.createElement('i');
control.className = 'custom-center-control mapboxgl-ctrl fas fa-map-marker-alt pointer';
this.container.appendChild(control);
return this.container;
}
}
location.component.scss:
.custom-center-control {
font-size: x-large;
color: green;
&:hover {
color: $cities-orange-light;
}
}
I can't figure out why the style gets applied to the one outside the map but not to that CustomControl inside the map.
How can i make it work?
Let me know if you need further information.
Try the encapsulation method add this encapsulation: ViewEncapsulation.None
to your decorator :
Example :
#Component({
selector: 'my-custom-input',
templateUrl: 'src/my-custom-input.component.html',
styleUrls:['src/my-custom-input.component.css'],
encapsulation: ViewEncapsulation.None
})
Related
I want to allow users to customize colors and some styles in Angular application. For that I want to make something like this
Structure:
component-one
folder-with-css-files
style-for-component-1-for-client1.css
style-for-component-1-for-client2.css
style-for-component-1-for-client3.css
style-for-component-1-for-client4.css
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.style-for-component-1-for-client{clientId}.css'],
})
export class AppComponent implements OnInit {
clientId: string;
ngOnInit(): void {
// pseudocode
clientId = service.fetchClientId() // for example
}
}
How I can achieve that? I want to have some css files for every component and depend on user id I want to assign them to styleUrls. Someone can tell me how to do it?
You can use scss and wrap every stylesheet in a different class then based on the user’s selection change the class of your body.
Something like:
DarkMode.scss
.darkMode{
your first css here…
}
LightMode.scss
.lightMode{
your second css here…
}
index.html:
<body class="lightMode"></body>
Doing the above will by default apply the lightMode styling and if you remove the classes of your body in any of your components and replace it with darkMode then the darkMode styling will apply.
Adding/Removing class to/from body:
constructor(private renderer: Renderer2) {}
addClass(){
this.renderer.addClass(document.body, 'className');
}
removeClass(){
this.renderer.removeClass(document.body, 'className');
}
Adding/Removing the class does not have to be only in the index.html file, all you need to do is have a tag with a certain class that wraps around your whole code. For example in one of your components:
component.html:
<div [class]="className">
the rest of your html here...
</div>
component.scss:
.greenDefault{
green default css here...
}
.redDefault{
red default css here...
}
.greyDefault{
grey default css here...
}
component.ts
className: string;
changeStyle(class: string){
this.className = class;
}
I'm learning Angular, and I'm working on a project ,in which, I need to use a CSS grid layout. However, I'm trying to find a way to insert a component inside a grid with given grid-area.
I tried to do this, <app-slots></app-slots>, in app.component.html but the component <app-slots> was counted as one grid place only; even though, it's 42 places.
slots.component.html:
<div class="abc" *ngFor="let in of getArrayOfNumbers(42) ;let i = index" [style.grid-row] = "i+1" style = "height:20px" > {{in}} </div>
slots.component.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-slots',
templateUrl: './slots.component.html',
styleUrls: ['../../app.component.css']
})
export class SlotsComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
getArrayOfNumbers(x: number){
var slots:number[] = [];
var a: number = x;
while(x != 0){
slots.push(x);
x--;
}
return slots;
}
}
Note: If something is not clear please tell me to add more info
can you just insert the component between your tags (instead of {{in}}), then send whatever updating variables from the .ts file through that using angular's binding feature ?
two way binding
When looking to the ngx-bootstrap source code here:
modal-options.class.ts
There is an optional class property defined as class?: string;.
What is the way to use it ?
Is it possible to add a custom class like:
this.modalService.config.class = 'myClass';
Before using the servive as for example:
this.modalRef = this.modalService.show(template, {
animated: false
});
This way, I think we can add custom CSS to the displayed modal
I've tried to add a custom class without success.
That class property is not an array, if applicable, does it mean that we can only add one custom class ?
Demo: by adding and overriding the modal class, the modal is not showing
https://stackblitz.com/edit/ngx-bootstrap-3auk5l?file=app%2Fapp.component.ts
Adding the modal class this way do not help:
this.modalRef = this.modalService.show(template, Object.assign({},
this.config, { class: 'gray modal-lg modal' }));
https://stackblitz.com/edit/ngx-bootstrap-awmkrc?file=app%2Fapp.component.ts
According to the ngx-bootstrap documentation about the Modal component (see the component tab), you can add a class member to the config object.
Important: Since the modal element is outside of the component element in the rendered HTML, the CSS encapsulation should be turned off for the component, or the style attributes for the class should be specified in another file, to make sure that the styles are applied to the modal element.
The code snippet below can be executed in this stackblitz.
import { Component, TemplateRef, ViewEncapsulation } from '#angular/core';
import { BsModalService, BsModalRef } from 'ngx-bootstrap';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
modalRef: BsModalRef;
config = {
animated: true,
keyboard: true,
backdrop: true,
ignoreBackdropClick: false,
class: "my-modal"
};
constructor(private modalService: BsModalService) { }
openModal(template: TemplateRef<any>) {
this.modalRef = this.modalService.show(template, this.config);
}
}
with a CSS file like this:
.my-modal {
border: solid 4px blue;
}
.my-modal .modal-header {
background-color: lime;
}
.my-modal .modal-body {
background-color: orange;
}
Update: This other stackblitz shows an example of CSS styles imported from an external file into styles.css, allowing to keep the CSS encapsulation in the component.
I am trying to implement theming in Angular2 project.
When someone change theme of web app, it will change the class of body using javascript. And each component in an application has relevant colors for each theme.
Can someone suggest me how to do this in Angular2 components.
when I write my component stylesheet with
body.theme-1 .header {
background-color: red;
}
it doesn't work.
Any other way to implement this.
If I cut same css from component stylesheet and put in to index.html or common stylesheet, it works. But it is a huge application and I don't want to write all component styles in to once place. Not manageable.
If you declare ViewEncapsulation.none in your component the styles from that component will apply globally to your application.
import { Component, ViewEncapsulation } from '#angular/core';
#Component({
selector: 'style-test',
template: `<div> Global stylesheet</div>`,
styles: ['body {
background: blue;
}'],
encapsulation: ViewEncapsulation.None // Use to
//disable CSS
//Encapsulation
//for this component
})
export class SecondComponent {
constructor() { }
}
I found answer from Angular2 documentation.
You can use :host-context() function
:host-context(.theme-1) .header {
background-color: red;
}
It works like a charm.
https://angular.io/docs/ts/latest/guide/component-styles.html
Check above link for further information
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' " />