How does ng-deep work internally in Angular - javascript

I'm trying to figure out how exactly ::ng-deep selector works. How does it omit random nghost and ngcontent attributes names?
Thanks in advance

if you use ::ng-deep in a component where view encapsulation is turned off, it stays there. Since this is invalid CSS, some rules break. It's silent and partial failure because CSS parser simply sees ::ng-deep as unknown selector.
If we want our component styles to cascade to all child elements of a component, but not to any other element on the page, we can currently do so using by combining the :host with the ::ng-deep selector.
:host ::ng-deep h2 {
color: red;
}
FYI: The ::ng-deep pseudo-class selector also has a couple of aliases: >>> and /deep/, and all three are soon to be removed.
https://blog.angular-university.io/angular-host-context/
How and Where to use ::ng-deep?

Related

What is the difference between using :host and not using it?

I found the usage of :host in angular is very confusing.
For example, there is a CSS file a-component.component.css, and its related HTML file is a-component.component.html whose selector is app-a-component.
And in the CSS file there is a statement
h1 {
font-size: 12px;
}
I think this CSS only applies to the <app-a-component> HTML element beased on the following explanation, is that correct?
And if I change the CSS to
:host h1 {
font-size: 12px;
}
(adding :host)
it will still applies to the same <app-a-component> HTML element, because it is the host HTML element of this component, is that correct?
If they are both correct, why would we need :host given it is the same effect with or without it?
Thanks in advance!
In your example :host h1 { ...} there's no difference. Where the :host becomes useful is when you need to use ::ng-deep or you want to style the host element.
e.g.
You have a component <my-component></my-component> and you want to apply styles directly to that element. You can add the styles with the :host selector.
:host {
background: red;
}
This will set the background of the my-component element to red.
For :host ::ng-deep { ... you can disable ViewEncapsulation for that rule but ONLY for descendant components. If you were to just use ::ng-deep without the :host that will become a global style.

How to style css of ionic2-calendar?

I'm working on an app with Ionic 5.0.0, Angular 8 and using the ionic2-calendar plugin. Although the plugin demo works fine, I can't seem to modify the styling of the calendar.
The documentation lists a couple of classes that seem to be used for each element, but adding them to my own scss file and adding !important (or not) doesn't really work. I tried adding them to the global scss, as well as to the main app one.
Aside from that, I've tried using the browser inspector to check which css selector is actually styling the elements in question, but the attribute selector seems to be random somehow. Current day for example is:
.monthview-current[_ngcontent-ljn-c3]
And after reloading, it is
.monthview-current[_ngcontent-igq-c4]
So clearly that method won't work either... I've also tried adding td.monthview-current, which also didn't work... Those were the suggestions and sample codes I've found from looking up this plugin online and looking around the plugin files. If anyone has any ideas whatsoever I'd be super thankful.
EDIT: I've found a way to change it, but ONLY through the source files for the plugin, which I have to assume is not the right way to do it... There's JSON files, JS files, and I have to manually change all of them.
If the styles are present inside the angular component's file it will not be applied due to view encapsulation. You need to specify the styles in the global stylesheet, and also in most you need to add important to the styles.
To elaborate further,
-src
-assets
-calendar.css (add styles here)
-app
-my-calendar
-my-calendar.page.html
-my-calendar.page.ts
-my-calendar.page.css (and not here)
Some commonly needed customizations: (assets/calendar.css)
Apply styles to the selected date:
.monthview-selected{
font-weight: bold;
background-color: #F1F1F1 !important;
color: #333 !important;
}
Apply styles to the date that has an event:
.monthview-primary-with-event, .calendar-event-inner{
background-color: #1a92d0!important;
}
Disable all the borders in the calendar:
td, th {
border: 0 !important;
}
Final calendar after applying the styles:
HTML
<calendar [eventSource]="eventSource" [calendarMode]="calendar.mode" [currentDate]="calendar.currentDate"
(onCurrentDateChanged)="onCurrentDateChanged($event)" (onRangeChanged)="reloadSource(startTime, endTime)"
(onEventSelected)="onEventSelected($event)" (onTitleChanged)="onViewTitleChanged($event)"
(onTimeSelected)="onTimeSelected($event)" step="30" (showEventDetail)="true" formatDayHeader="EEEEE"
allDayLabel="All Day" startHour="9" endHour="20">
</calendar>
I had the same issue and a solution is related to encapsulation as stated in other answer.
Styling not applying to child component
try update your component:
#Component({
...
encapsulation: ViewEncapsulation.None // <------
})
export class xxComponent{
You can then apply the style based on the child class, eg.
.scss:
.monthview-container {
...;
}
The best way is to use Template Customization given in the plugin.
https://github.com/twinssbc/Ionic2-Calendar/blob/v6/README.md#Template Customization
If that is diffcult in your case. Then add a class to calender tag in html. And get all the child elements in css using Child or descendent combinator. Css Combinator
Although I'm not sure about the reason for this, the solution in my case seems to be using the global stylesheet (without any attribute selector in brackets) instead of the module specific one. It's not ideal, but it works I guess!
With depp
::ng-deep {
.monthview-selected {
background-color: blue !important;
color: white !important;
border-radius: 50%;
}
}

quirks of using Angular Shadow DOM CSS Selector

I'm new to Angular, just a question on applying Shadow DOM CSS Selector. Below is some pseudo code:
//root template.html
<div id="first">
<div id="second">
<paProductForm ..."></paProductForm>
<div>
</div>
where paProductForm is the selector of my custom component as:
#Component({
selector: "paProductForm",
templateUrl: "productForm.component.html",
styles: ["/deep/ div { border: 2px black solid; font-style:italic }"]
})
export class ProductFormComponent {
...
}
I was told that /deep is used by a parent component to define styles
that affect the elements in child component templates, so that means in my case, the style should only apply to <div> inside productForm.component.html and also child components if it has.
But it actually setup a global style element in the head of the client side of html as
which means that the style will also apply on "div" elements with id of "first" and "second", which is not what I want and not the goal of /deep as it claims to be?
According To Angular Documentation:
Applying the ::ng-deep pseudo-class to any CSS rule completely disables view-encapsulation for that rule. Any style with ::ng-deep applied becomes a global style. In order to scope the specified style to the current component and all its descendants, be sure to include the :host selector before ::ng-deep. If the ::ng-deep combinator is used without the :host pseudo-class selector, the style can bleed into other components.
/deep and ::ng-deep are the same, except ::ng-deep is supported by SASS, (both of which are marked deprecated and should be avoided)
From: Adam Freeman Book “Pro Angular 9.” :
Using the shadow DOM means that there are boundaries that regular CSS selectors do not operate across. To help address this, there are a number of special CSS selectors that are useful when using styles that rely on the shadow DOM (even when it is being emulated), as described below:
:host
This selector is used to match the component’s host element.
:host-context(classSelector)
This selector is used to match the ancestors of the host element that are members of a specific class.
/deep/ or >>>
This selector is used by a parent component to define styles that affect the elements in child component templates. This selector should be used only when the #Component decorator’s encapsulation property is set to emulated.

Cannot style Jquery element using CSS

I have a Jquery selectmenu called #Main which implicitly gets a #Main-button. When I try to set #Main-button's width using css as
#Main-button {
width:200px;
}
it has no effect.
When I explicitly set
$( "#Main" ).selectmenu({ width:200})
it has the desired effect and under Firebug I see that it has appended a style="width:200" on the #Main-button, which is what I tried using CSS at the first place.
What is different? I've checked that the my CSS style sheet gets called AFTER the Jquery one, so there is no precedence issue
Also I notice that html elements turned to Jquery elements cannot be styled using CSS targeted at the specific element, even with the use of unique id's,but require the use of Jquery classes like .ui-menu etc
why do they behave differently? are there any specific styling gudilines when Jquery is involved?
In your CSS you've
#Main-button {
width:200px;
}
but the JS is adding dynamic inline style based on content. So it's having style attribute.
So in terms of CSS specificity their CSS beats you.
You must use !important in your rule to avoid overriding of your CSS.
#Main-button {
width:200px !important;
}
To style selectmenu or every jquery widget, you need to use jquery default classes. Your selector must be like
#Main-button.ui-selectmenu-menu li a
And also you can extend _renderItem and _renderMenu functions of selectmenu for different styling.

css: changing the ruleset vs using selectors to switch classes/apply styles

Lately I wondered about editing elements styles not by switching their classes on dom, but by changing the actual ruleset for the css class or selector.
So instead of something like
$('.some').hide()
or
$('.some').addClass('hidden')
Why not alter a rule directly with document.styleSheets and stuff?
Wouldn't this approach be generally more performant, at least with many elements, as we'd let the browser handle the ruleset changes natively?
You could for example add an style to .some, like display: none; and all .some elements would be immedeatly be hidden. There is no need to iterate over all those elements in js and hide them manually(like the example above).
Changing rulesets directly would more likely encourage classes that are context aware(or however you would call this..), as you'd hide all #persons > .item or something.
I still don't know best practices regarding classes that are named with context in mind, like for example control names like .calendar .ticket .item, versus single functionality classes like .hidden .left .green, as I usually need both types of conventions.
I am just asking what you think about this and what are benefits and drawbacks of the modifiying stylesheet approach versus how libraries like jquery handle changing styles?
Also, what do you think is good practice, what do you regard more as a hack?
cough javascript and hacking cough
Manipulating document.styleSheets is tricky due to differing implementations and the lack of a rule selector API. Currently if you want to manipulate a rule in a stylesheet you have to go through this process:
iterate over document.styleSheets
iterate over rules within current styleSheet object
if rule matches our class, edit the rule styles
Then there's the cascading issue. How do you know that a particular style on the rule you've matched won't be overridden by a different rule somewhere in the pages stylesheets? If you just bail out after changing the first matching rule you find, you can't be sure that the styles you set will actually be applied to the element, unless you stick an !important on each one, which will leave you with a whole different set of problems.
Even when you've manipulated the style sheet rules, the browser still has the same job to do — it has to recalculate all the styles by applying the cascade.
So, manipulating styleSheets doesn't look too appealing now, does it? Stick to class switching, trust me. Using jQuery and modern APIs like querySelectorAll make it plenty fast and the browser still does all the hard work like recomputing the style values.
Such a tricky question :(
But if you take boilerplate for instance, it has a some standard classes to use like:
/* Hide from both screenreaders and browsers: h5bp.com/u */
.hidden { display: none !important; visibility: hidden; }
/* Hide only visually, but have it available for screenreaders: h5bp.com/v */
.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: ; position: absolute; width: 1px; }
/* Hide visually and from screenreaders, but maintain layout */
.invisible { visibility: hidden; }
Where it gets tricky is, IF it is something you need to hide because of JS, then you should ONLY hide it with JS. Then it will function if JS is disabled.
If it is something that is not JS dependent, then you hide it in the HTML.
So JS function = hide with JS (either by using JS or adding hide classes)
Basic HTML hide = hide with HTML class
Styleswitching vs JS switching
Basicly JS switching gives you the oppertunity to add effect etc, just using predefined classes limits that somewhat. But would love to see some ressource comparisons :)

Categories

Resources