My angular project is reading from a library that contains this code is a class:
class MyClass extends EventEmitter {
constructor () {
// add the element to the container
this.loadingElement = document.createElement('div');
this.loadingElement.className = "loading"
this.loadingElement.innerText = 'Now Loading...';
}
}
In my app.component.css I have this:
#componentDivId .loading {
position: absolute;
top: 50%;
left: 50%;
}
This css is in app.component.css
How can I change this so it reads the css?
You should look into ::ng-deep for overriding component styling. Also, may need to use !important in css file as and when required
Here is a demo code to help you understand how ::ng-deep can be used to push styling to a child component.
Related
Height is not added properly in the modal body when the modal is opened as a separate component using ng-bootstrap.
Issue exist on below stackblitz link
https://stackblitz.com/edit/angular-xwqusl?file=src%2Fapp%2Fmodal-component.ts
Working Example:
It was working as expected without a separate component.
https://stackblitz.com/edit/angular-tfpf81?file=src%2Fapp%2Fmodal-options.ts,src%2Fapp%2Fmodal-options.html
Does anyone know about this issue?
Thank you for the stackblitz, I think the issue is due to view encapsulation - being set as none, so css didn't get applied.
In Angular usually the html element with the component selector ngbd-modal-content will not take the height of the parent, we need to manually adjust it with css, its a pain point of angular!
// encapsulation: ViewEncapsulation.None, // <- remove this
styles: [
`
:host {
display: flex;
flex-direction: column;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
border: solid 3px yellow; /* for debugging purposes */
}
`,
],
forked stackblitz
I have been struggling with this for a quite some time now, and i couldn't find a sufficient answer. Basically i have one parent component which html goes as follows:
<div class="container">
<child-one></child-one>
<child-two></child-two>
</div>
the problem is that the child-one component has its size set as auto, with some padding to look good,
child-one {
width: auto;
height: auto;
padding: 0.5rem;
}
and child-two has a fixed width and height in it's own scss.
child-two {
width: 10rem;
height: auto;
}
is there a way to somehow change the width of child-two in the parent without editing the child-two?
I was hoping for something along the lines of storing the width of the child-one, and setting the width of child-two to the same value.
child-one {
width:auto;
padding: 0.5rem;
$width: this.width !global //idk about this one
}
child-two {
width: $width
padding: 0.5rem
}
please note that the child-one and child-two scss don't look this way in the code, and are normally written, this is just for the purpose of simplifying the question
Is this what you are looking for?
app.component.html - Parent Component
<child-one #childOne></child-one>
<child-two #childTwo></child-two>
<br>
<button (click)="changeWidth()">Change child two width</button>
app.component.ts
export class AppComponent {
#ViewChild('childOne', {
read: ElementRef
}) childOne: ElementRef;
#ViewChild('childTwo', {
read: ElementRef
}) childTwo: ElementRef;
constructor(private renderer: Renderer2) {}
changeWidth() {
const childOneWidth = this.childOne.nativeElement.getElementsByClassName('child-one')[0].offsetWidth;
const childTwoElement = this.childTwo.nativeElement.getElementsByClassName('child-two')[0];
this.renderer.setStyle(childTwoElement, 'width', `${childOneWidth - 2}px`);
}
}
Here is the working Stackblitz
Suggestion
#SivakumarTadisetti's suggestion is a valid suggestion, alternatively, you could use ngStyle to provide dynamic styling for the component or ngClass for conditionally applying style class to the component. You could, which requires more code, also write a directive that changes the style behaviour of the component based on certain conditions.
Example using ngStyle
https://stackblitz.com/edit/stack-help-01
How could I change the mat-radio-button to check-mark and cross-mark looks like following?
Thank you!
My code is here:
<mat-radio-group class="radio" (change)="onChange($event)"
name="exemplars">
<mat-radio-button class="radio-custom" [value]="true" [checked]="function()"> Accept </mat-radio-button>
<mat-radio-button class="radio-custom" [value]="false" [checked]="function()"> Reject</mat-radio-button>
</mat-radio-group>
icons I want to use :
Don't think this is the most elegant solution but it does the job.
In my case I'm using Angular 10 (2+) with all the ::ng-deep stuff so align the code for your needs.
I'm using an icomoon font with the icons my company is using so take this into consideration when applying this solution.
In my app.component. styling file:
::ng-deep {
.mat-radio-button {
.mat-radio-container {
.mat-radio-outer-circle:before {
font-family: "icomoon" !important; // here comes the icomoon font reference that defines the actual icon to be shown
content: "\e901"; // the code of the icon from my iconfont => change this one to the X icon of yours
position: absolute; // this and next 3 lines are for centering the icon in the circle of the radio button
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.mat-radio-inner-circle {
/* feel free to design the actual inner radiobutton circle as you wish*/
}
}
.mat-radio-button .mat-radio-checked {
.mat-radio-container {
.mat-radio-outer-circle:before {
content: "\e900"; // the code of the icon from my iconfont => change this one to V icon of yours
}
}
}
}
}
Feel free to enhance the code with all other stuff: sizes, borders, coloring, etc.
Create a new directive that binds to mat-radio-button or any other selector you need, e.g. mat-radio-button.radio-custom
Inject ElementRef into the directive's constructor
Use the instance of ElementRef to find .mat-radio-inner-circle
Set the innerHTML of the found html element to the svg of your desired icon.
Example:
#Directive({
selector: 'mat-radio-button',
})
export class CustomRadioButton implements OnInit {
constructor(private elementRef: ElementRef) {}
ngOnInit() {
this.appendIcon();
}
appendIcon() {
const innerCircle = this.elementRef.nativeElement.querySelector('.mat-radio-inner-circle');
innerCircle.innerHTML = YOUR_SVG_CODE;
}
}
I have a custom element (without shadow DOM) that I'd like to be able to use anywhere, even inside another custom element that might use shadow DOM. However, I'm not sure how to get the styles working in both places.
For example, lets say I create a simple fancy-button element:
class fancyButton extends HTMLElement {
constructor() {
super();
this.innerHTML = `
<style>
fancy-button button {
padding: 10px 15px;
background: rgb(62,118,194);
color: white;
border: none;
border-radius: 4px
}
</style>
<button>Click Me</button>`;
}
}
customElements.define('fancy-button', fancyButton);
<fancy-button></fancy-button>
Inside a shadow DOM element, the inserted style tag will allow the fancy-button styles to work. However, if this component gets used outside of a shadow DOM element, the style tag will be duplicated every time the element is used.
If instead I add the style tag as part of the html import file, then the styles only work outside of the shadow DOM but at least they are only declared once.
<!-- fancy-button.html -->
<style>
fancy-button button {
padding: 10px 15px;
background: rgb(62,118,194);
color: white;
border: none;
border-radius: 4px
}
</style>
<script>
class fancyButton extends HTMLElement {
constructor() {
super();
this.innerHTML = `<button>Click Me</button>`;
}
}
customElements.define('fancy-button', fancyButton);
</script>
What's the best way to add custom element styles that handles both being used inside and outside the shadow DOM?
So I was able to find a solution thanks to Supersharp suggestions about checking if we're in the shadow DOM.
First you add the styles as part of the import file so that the styles apply outside of the shadow DOM by default. Then when element is added to the DOM, we check getRootNode() to see if it's been added to a ShadowRoot node. If it has, and the styles haven't already been injected into the root, then we can inject the styles manually.
var div = document.createElement('div');
var shadow = div.attachShadow({mode: 'open'});
shadow.innerHTML = '<fancy-button></fancy-button>';
document.body.appendChild(div);
<style data-fs-dialog>
fancy-button button {
padding: 10px 15px;
background: rgb(62,118,194);
color: white;
border: none;
border-radius: 4px
}
</style>
<script>
class fancyButton extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.innerHTML = `<button>Click Me</button>`;
var root = this.getRootNode();
// In polyfilled browsers there is no shadow DOM so global styles still style
// the "fake" shadow DOM. We need to test for truly native support so we know
// when to inject styles into the shadow dom. The best way I've found to do that
// is to test the toString output of a shadowroot since `instanceof ShadowRoot`
// returns true when it's just a document-fragment in polyfilled browsers
if (root.toString() === '[object ShadowRoot]' && !root.querySelector('style[data-fs-dialog]')) {
var styles = document.querySelector('style[data-fs-dialog]').cloneNode(true);
root.appendChild(styles);
}
}
}
customElements.define('fancy-button', fancyButton);
</script>
<fancy-button></fancy-button>
When all browsers support <link rel=stylesheet> in the shadow DOM, then the inline script can turn into an external stylesheet as robdodson suggested, and the code is a bit cleaner.
You'll probably want to put the styles in a separate CSS file that you vend along with your element's JS. But as you've pointed out, if you put the element inside the Shadow DOM of another element then the styles won't work in that scope. For this reason it's usually best to just create a shadow root and pop your styles in there. Any reason why you wouldn't want to do that?
After trying to find an example where the FloatingActionButton floats at its standard bottom-right screen position with no results, I come to you if you could provide one because it seems to be a normal button without floating to that corner by default.
Am I supposed to make it float by setting custom CSS rules?
Material-UI docs doesn't mention any property about floating Material-UI FloatingActionButton documentation.
Indeed, no property for this in the component FloatingActionButton for the moment.
Waiting for it :
1) A solution using inline styles :
At the top of your component, add :
const style = {
margin: 0,
top: 'auto',
right: 20,
bottom: 20,
left: 'auto',
position: 'fixed',
};
... and in your render method :
render() {
return <FloatingActionButton style={style}><ContentAdd /></FloatingActionButton>
}
OR
2) A solution using CSS file
Add in your CSS file (ex : styles.css referenced on your index.html) :
.fab {
margin: 0px;
top: auto;
right: 20px;
bottom: 20px;
left: auto;
position: fixed;
};
... and put on your React component :
render() {
return <FloatingActionButton className="fab"><ContentAdd /></FloatingActionButton>
}
I actually found this on the Material-UI documentation. I just made a few tweaks to it. Here's the resulting code.
import { makeStyles } from '#material-ui/core/styles';
import Fab from '#material-ui/core/Fab';
import AddIcon from '#material-ui/icons/Add';
const useStyles = makeStyles(theme => ({
fab: {
position: 'fixed',
bottom: theme.spacing(2),
right: theme.spacing(2),
},
}));
add this to your component
const classes = useStyles();
return (
<Fab color="primary" aria-label="add" className={classes.fab}>
<AddIcon />
</Fab>
);
If you want to manipulate CSS in material-ui, its better to use withStyles currying function.
Like this:
import React, {Component} from 'react';
import {Button} from "material-ui";
import {Add} from 'material-ui-icons';
import { withStyles } from 'material-ui/styles';
const style = theme => ({
fab: {
margin: 0,
top: 'auto',
left: 20,
bottom: 20,
right: 'auto',
position: 'fixed',
}
});
class MyPage extends Component{
render() {
const {classes} = this.props;
return <Button fab variant="fab" color="primary" aria-label="add" className={classes.fab}><Add />
</Button>
}
export default withStyles(style)(MyPage);
Documentation link: https://material-ui.com/customization/css-in-js/
In MUI v5, you can add the one-off styles directly to the Fab component via the sx props. Set the position to fixed (as opposed to absolute in other answers*) along with the anchor positions and you're done.
return (
<Fab
sx={{
position: "fixed",
bottom: (theme) => theme.spacing(2),
right: (theme) => theme.spacing(2)
}}
color="primary"
>
<AddIcon />
</Fab>
);
*: Setting to absolute will anchor the button to the bottom right of the closest relative container, the container itself will be moved if the user scrolls down which in turn moves the button. Use fixed value to anchor the button in relative to the viewport, so the scrolling would not affect the button position.
If you are creating a custom theme you can use the theme overrides to style the FAB (Floating Action Button) is floating in the bottom right corner:
import { createMuiTheme } from "#material-ui/core";
export default createMuiTheme({
overrides: {
MuiFab: {
root: {
position: 'absolute',
bottom: '2rem',
right: '2rem'
}
}
}
});
This will override the FAB for every component usage. You can use the same style with a specific class name and override it again for other usages.
In case of custom theme, in MUI v5 the overriding of the style it's a bit different from the v4,
see MUI v5-style-changes.
components: {
MuiFab: {
styleOverrides: {
root: {
position: 'fixed',
bottom: '2rem',
right: '2rem'
}
}
}
}