Reputation: 19814
I have DOM that looks something like this:
<app>
<router-outlet></router-outlet>
<project>...</project>
</app>
where project
element is inserted by the router.
How do I add a class to this element?
Upvotes: 67
Views: 51807
Reputation: 21
After the deprecation of ::ng-deep
in Angular, the proper way to use the solution provided in @Val's comment is to set the style in a CSS not bind to a specific component.
Usually, you have in your angular.json file a list of styles declared as follows:
"projects": {
"n9-skeleton-ng-cli": {
"root": "",
"architect": {
"build": {
"options": {
"styles": [
"src/app/app.module.scss"
]
}
}
}
In one of these styles files, use a selector that will target that router specifically and add the sibling selector.
For instance, to not target every router-outlet in the application, you can add a class on the targeted ones .router-styled
, then target it: in src/app/app.module.scss
router-outlet.router-styled + * {
/* your css */
}
Upvotes: 0
Reputation: 171
I know it's late.
I created this directive to allow you to set (static) or bind (dynamic) classes to each component that is injected by Angular next to the router-outlet
element:
https://www.npmjs.com/package/ngx-router-outlet-class
Please upvote my feature request if you DO think it's necessary to have such a built-in functionality.
Upvotes: -1
Reputation: 31
it's simple, let's say in your app component you have a
<router-outlet ></router-outlet>
inside this router-outlet you have a route component called
<app-product-detail></app-product-detail>
and you want to change the view of in the app.component.html.
first inside the the component <app-product-detail>
add this snippet:
@Component({
selector: 'app-product-detail',
host: {
class:'Project-wrapper'
},
templateUrl: './product-detail.component.html',
styleUrls: ['./product-detail.component.css']
})```
class= 'could be any name'
inside app.component.css you add this snippet below:
::ng-deep .Project-wrapper {
width: 85%;
background-color: aqua;
}
Upvotes: 0
Reputation: 17
Add host class name which will add a class to the component then use adjacent to target the element.
@Component({
selector:'project',
host: {
class:'Project-wrapper'
}
})
now use CSS adjacent with angular
::ng-deep to target it:
::ng-deep .Project-wrapper {}
Upvotes: 0
Reputation: 32670
Assuming you always want the class applied to this component, you can use host
in your component metadata:
@Component({
selector:'project',
host: {
class:'classYouWantApplied'
}
})
Resulting in:
<app>
<router-outlet></router-outlet>
<project class="classYouWantApplied">...</project>
</app>
Upvotes: 78
Reputation: 1996
For me it helped to wrap the router-outlet into another container.
<div class="classYouWantApplied">
<router-outlet>
</div>
Like this you could apply the class to the surrounding container.
Upvotes: 3
Reputation: 1305
since router injects the component after the the router-outler element, if we would like to style all injected component with the same set of rules the folowing rule is can be helpful.
the css "+" operator select the first sibling element of a certain type, while asterisk (*) is used as a wild card to select any 1st sibling of router-outlet
router-outlet + * {
// your rules
}
Upvotes: 4
Reputation: 145890
I created a RouterOutletHelperDirective
which can be modified as necessary.
Your use-case may be different but for me :
ActivatedRoute
data.You use it like this (the class is optional):
<router-outlet routerOutletHelper
[routerOutletHelperClass]="'blue-border'"></router-outlet>
Then create the directive, add and export it to your app module.
import { Directive, ElementRef, Renderer2, Input } from "@angular/core";
import { RouterOutlet } from "@angular/router";
import { Subscription } from "rxjs";
@Directive({
selector: 'router-outlet[routerOutletHelper]'
})
export class RouterOutletHelperDirective
{
constructor(private routerOutlet: RouterOutlet,
private element: ElementRef<HTMLElement>,
private renderer: Renderer2) { }
subscription = new Subscription();
@Input('routerOutletHelperClass')
customClassName: string | undefined;
ngOnInit()
{
this.subscription.add(this.routerOutlet.activateEvents.subscribe((_evt: any) => {
// find the component element that was just added
const componentElement = this.element.nativeElement.nextSibling;
// add a custom class
if (this.customClassName)
{
this.renderer.addClass(componentElement, this.customClassName);
}
// add my default classes, unless the activated route data
// (specified in module routing file) has { addDefaultClasses: false }
if (this.routerOutlet.activatedRouteData && this.routerOutlet.activatedRouteData.addDefaultClasses !== false)
{
// these are my application's default classes (material / theming)
// (an additional data parameter could be 'darkTheme: boolean')
this.renderer.addClass(componentElement, 'mat-typography');
this.renderer.addClass(componentElement, 'rr-theme-light');
}
}));
}
ngOnDestroy()
{
this.subscription.unsubscribe();
}
}
Upvotes: 1
Reputation: 169
Currently, Angular 6 recommends me to use @HostBindings and @HostListeners instead of the host property:
export class ProjectComponent {
@HostBinding('class') classes = 'classYouWantApplied';
}
Upvotes: 5
Reputation: 1694
use the adjacent sibling selector
and the *
wildcard to select the element immediately following the router-outlet
styles.css
router-outlet + * {
/* your css */
}
Upvotes: 29
Reputation: 319
<app>
<div class="your css class">
<router-outlet></router-outlet>
</div>
</app>
This works for me
Upvotes: 5
Reputation: 22797
The key is /deep/ keyword:
:host /deep/ router-outlet + project {
display: block;
border: 10px solid black;
}
This works without any extra configurations.
:host /deep/ router-outlet + *
for whatever component dynamically created by Angular Router.
Since Angular 4.3.0 made /deep/
deprecated, its suggested alternative is ::ng-deep
. And there were a long discussion about this.
Upvotes: 14
Reputation: 4105
You can do this with a HostBinding
, which is effectively the same as using the host
property that has already been mentioned, although that method throws a TSLint error with default listing rules.
In your component on which you want to apply a class:
import { Component, HostBinding, Host (optional for typing) } from '@angular/core';
@Component({...})
export class GiveMeAClassComponent {
@HostBinding('class.some-class') someClass: Host = true;
...
}
And then in your root styles.scss
file, you can add the following:
.some-class {
// Styles in here will now be applied to your GiveMeAClassComponent at a root level
}
Upvotes: 6
Reputation: 12603
If you need to add a class conditionally, you can add it programmatically from the component:
constructor(private renderer: Renderer2, private elemRef: ElementRef) {
if(someCondition){
renderer.addClass(elemRef.nativeElement, 'myClass');
}
}
Upvotes: 3
Reputation: 657168
You can use the adjacent sibling selector
router-outlet + project { ... }
https://developer.mozilla.org/en/docs/Web/CSS/Adjacent_sibling_selectors
but only if @drewmoore's approach doesn't apply.
Upvotes: 5