Angular - CSS properties of added class not showing - html

I'm appending a childitem div to another div inside the same angular component. Then I assign a class to it. (using class list) It succesfully inserts the element and also adds the class to it but non of my css class properties are applied to it.
If I add the element manually inside my html code (including the class attribute) the element is shown correctly.
Why is this happening?
Typescript code:
let parent = document.getElementById('playingfield');
let cactus = document.createElement('div');
cactus.classList.add('cactus');
parent.appendChild(cactus);
HTML code of manually inserting the div:
<div class="cactus"></div>

To apply the runtime css into your html you need to use :host feature of angular.
In your .css or .scss file set css by this way.
:host ::ng-deep .cactus{
// Your css hear
}

Related

CSS of one component causing unwanted formatting in another

I am still just learning in Angular, CSS, and HTML (all three are new), so have some patience with me please.
I received some code, and was given the task to fix some formatting.
Here is the problem:
When the page first loads, the page header has some padding. See picture below on the left.
However, when I navigate to another page, which has this code:
/* Removing padding and scroll bar from main page */
::ng-deep html > body > main#app-content {
overflow-y: hidden;
padding: 0;
}
and then navigate to any other component/page, the padding is gone and everything is moved all the way to left of the screen, which is very annoying. See picture below on the right. Note: someone told me that this is the code that is causing this situation, and I actually have no idea what it is actually doing (besides setting the padding and y-scroll).
This picture shows two components/pages before I access the page with the code above (shown on the left side in the picture), and then after I navigate to that page with the code above (shown on t eh right side in the picture). Note the green line is for reference to show how the padding is gone.
So I would like to have the original padding/formatting back when I navigate back to it after I access the page with the code above.
Also, can someone explain to me why it's doing this? And if possible, what does the code actually mean? Here are some specific questions:
How can I stop this from happening on another page?
What does "::ng-deep html > body > main#app-content" mean?
What does the greater sign do?
TLDR: Here is a stackblitz with an example of how to edit a global style using a service rather than ::ng-deep. https://stackblitz.com/edit/angular-ivy-p4pkdu?file=src/app/app.component.html
::ng-deep is an angular feature that promotes the following css to apply globally (everywhere in your application). It should really be avoided, as there is usually a better way to apply global styles. This feature is actually being deprecated, I'll put an alternative at the end of this answer.
html > body > main#app-content is just a CSS selector. In this case we are selecting the main element with id app-content, which has body as a parent, which has html as a parent. Here is a good reference for CSS syntax: https://www.w3schools.com/cssref/css_selectors.asp.
So we are applying these css styles to an html element of type main and with id app-content, the style is applied globally, so it will still persist after the encapsulating component is destroyed.
A better alternative to ::ng-deep is to use a service to edit global styles. First off, any global styles should be stored or imported into the global styles file, usually called styles.css in an angular project. If you only need the style in one component, you can put this css in the respective component css file instead. We declare it as a class so we can add it to an element dynamically.
In styles.css
.noPaddingOrScrollbar {
overflow-y: hidden;
padding: 0;
}
Then generate a service with the cli using ng g service <serviceName>. For example, to generate a service named globalStyleService in a folder called services we do ng g service services/global-style. We'll add a boolean to our service to indicate whether we want the style applied or not.
One caveat is that we need to use setTimeout to set the boolean, to avoid the dreaded NG0100: Expression has changed after it was checked error. setTimeout will default to a timeout of zero, but will still delay the code execution until after Angular finishes a round of change detection.
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root',
})
export class GlobalStyleService {
private _noPaddingOrScrollbar = false;
set noPaddingOrScrollbar(value: boolean) {
//Delay setting until after change detection finishes
setTimeout(() => (this._noPaddingOrScrollbar = value));
}
get noPaddingOrScrollbar() {
return this._noPaddingOrScrollbar;
}
constructor() {}
}
Now you need to find in what component this main#app-content element is actually located. It'll be in the html file of one of the parent components. You can then inject the service into this parent component ts file, and set the class dynamically in the component's html file.
Parent component ts file
export class ParentComponent {
constructor(public globalStyle: GlobalStyleService) {}
...
}
We use the angular directive [class.className]="boolean" to set the class dynamically.
Parent component html file
...
<main
id="app-content"
[class.noPaddingOrScrollbar]="globalStyle.noPaddingOrScrollbar"
></main>
...
Now you can add or remove this class from anywhere in your application. So in the component containing the hacky css, we inject the service, add the style during ngOnInit and remove it during ngOnDestroy. Of course remove the ::ng-deep statement from the css file as well.
Child component ts file
export class MyComponent implements OnInit, OnDestroy {
constructor(private globalStyle: GlobalStyleService) {}
ngOnInit(): void {
this.globalStyle.noPaddingOrScrollbar = true;
}
ngOnDestroy(): void {
this.globalStyle.noPaddingOrScrollbar = false;
}
...
}

Styling body element in react without overriding the body on my other components

I have five-page folders. each folder has a CSS file and a js file. each js file is importing a component. that component is wrapped in the CSS class name. every time I try to style using an element like body or form, my styling on all other pages is overridden.
the only way I can style the body is by putting the styling in a class and wrapping it around the component. there has to be a better way. I'm trying to animate my screen and it takes a lot of styling elements directly.
import LandingPageComponent from "../../components/LandingPageComponent"
function LandingPage(){
return(
<div className=".landingpage">
<LandingPageComponent />
</div>
)
}
export default LandingPage; ```

What is the difference between class and [class] in angular html

Looking for good practices about angular folder structure I stumble upon this piece of code:
content-layout.component.html:
<div [class]="theme">
<div class="mat-app-background">
<app-nav></app-nav>
<div class="container">
<router-outlet></router-outlet>
</div>
<app-footer></app-footer>
</div>
</div>
As far as I understand, the class tag is used to bind this component HTML with a CSS class.
But the square brackets caught my attention, is there any real difference between the [class] and class for css binding? I can't hit the correct search term/feature name to google it myself
the brackets [] indicate that the value is a property in your component, so instead of saying apply the class theme to the element, it will look for a property theme in your component and use whatever is stored in there.
class="theme" // apply class theme
// Component
public theme = 'theme';
// HTML
[class]="theme" // use what's stored in property "theme"
or
[class]="'theme'" // use string 'theme'
[] is a way to bind the data between ts and HTML, so in this case, the theme is a variable, on the other side container is a direct property
what you understood about class is right, where coming to [class], based on the value, class will be applied to that element. if the value is true or some value then that class will be applied to that element or else it will ignore that class. so basically you are using a specific class for some functionality and not using it for another
eg: <div [class.classOne]="true"></div> // now div element will have classOne class because result is true or some value.
references for better understanding about classes:
https://angular.io/api/common/NgClass,
Difference between [ngClass] vs [class] binding

Access css class selector inside html document inside the app

I've got this piece of HTML:
<html>
...
<iframe>
#document
<html>
...
<div className='change-me'></div>
...
</html>
</iframe>
</html>
That iframe is taken from stripe React element, I want to access something inside it and change its CSS.
I've dealt before with libraries that offer reusable React components, and managed easily to change every CSS detail there.
Problem: But here I can change nothing.
.change-me { background: red } // This one doesn't work
Maybe it's the fact that the component is making it's own html document, maybe I'm looking at the problem from the wrong end...
Plain CSS is not going to work. You need to change the class of the element with your own class programmatically using JavaScript and the iFrame must contain the CSS file/styling containing that class
For example, you can add your CSS file to the iframe like this:
var iFrame = document.getElementById("youriFrameId");
var head = iFrame.getElementsByTagName("head")[0];
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'path/to/cssFile.css';
head.appendChild(link);
and then add your class to your target element like this:
iFrame.getElementById('targetElementId').classList.add("yourClass");

Why doesn't individual styling of a react component instance work?

I'm using the following instance of a react component in a view:
<Jumbotron>
Lot's of important content
</Jumbotron>
I want an individual style (i.e. a different background image for this instance. So this doesn't work:
<Jumbotron className="individual">
Lot's of important content
</Jumbotron>
Wrapping the instance in a div also doesn't work. How can I do this with simple markup and CSS so that I can simply style the individual class in CSS? AFAIK properties won't help to customize instances...
You can either pass in the style attribute or you can pass through the className attribute in the same way
<Jumbotron className="background--black">
And have your component like this -
const Jumbotron = ({className}) => {
<div className={className}>
Here is the jumbotron
</div>
}
export default Jumbotron
And import a css file that has that class in, if you're using className. But I would probably recommend just using style attribute if it's a one off.