如何将 css class 应用于由 router-outlet 创建的组件元素?

How to apply css class to a component element when it's created by router-outlet?

我有 DOM 看起来像这样:

<app>
    <router-outlet></router-outlet>
    <project>...</project>
</app>

其中 project 元素由路由器插入。

如何向该元素添加 class?

假设您始终希望将 class 应用于此组件,您可以在组件元数据中使用 host

@Component({
  selector:'project',
  host: {
      class:'classYouWantApplied'
  }
})

导致:

<app>
    <router-outlet></router-outlet>
    <project class="classYouWantApplied">...</project>
</app>

您可以使用相邻兄弟选择器

router-outlet + project { ... }

https://developer.mozilla.org/en/docs/Web/CSS/Adjacent_sibling_selectors

但前提是@drewmoore 的方法不适用。

关键是/deep/关键字:

    :host /deep/ router-outlet + project {
        display: block;
        border: 10px solid black;
    }

无需任何额外配置即可运行。

:host /deep/ router-outlet + * 对于由 Angular 路由器动态创建的任何组件。

2018/3/5 编辑:

因为 Angular 4.3.0 made /deep/ deprecated, its suggested alternative is ::ng-deep. And there were a long discussion 关于这个。

如果您需要有条件地添加 class,您可以从组件中以编程方式添加它:

constructor(private renderer: Renderer2, private elemRef: ElementRef) {
  if(someCondition){
    renderer.addClass(elemRef.nativeElement, 'myClass');
  }
}

您可以使用 HostBinding 执行此操作,这实际上与使用已经提到的 host 属性 相同,尽管该方法默认会抛出 TSLint 错误上市规则。

在您要应用的组件中 class:

import { Component, HostBinding, Host (optional for typing) } from '@angular/core';

@Component({...})
export class GiveMeAClassComponent {
    @HostBinding('class.some-class') someClass: Host = true;
    ...
}

然后在你的根 styles.scss 文件中,你可以添加以下内容:

.some-class {
    // Styles in here will now be applied to your GiveMeAClassComponent at a root level
}
<app>
  <div class="your css class">
   <router-outlet></router-outlet>
</div>
</app>

这对我有用

使用 adjacent sibling selector* 通配符 select 紧跟在 router-outlet

之后的元素


styles.css

router-outlet + * {
  /* your css */
}

目前,Angular 6 建议我使用@HostBindings 和@HostListeners 而不是主机属性:

export class ProjectComponent {
  @HostBinding('class') classes = 'classYouWantApplied';
}

我创建了一个 RouterOutletHelperDirective 可以根据需要进行修改。

您的用例可能不同,但对我而言:

  • 我需要在每个路由器出口生成的项目上设置一组默认的 classes
  • 我需要根据某些条件防止此默认设置,例如ActivatedRoute数据。

你这样使用它(class 是可选的):

<router-outlet routerOutletHelper
               [routerOutletHelperClass]="'blue-border'"></router-outlet>

然后创建指令,将其添加并导出到您的应用程序模块。

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();
    }
}

由于路由器在 router-outler 元素之后注入组件, 如果我们想使用同一组规则设置所有注入组件的样式,则以下规则可能会有所帮助。

css “+” 运算符 select 某种类型的第一个兄弟元素,而星号 (*) 用作 select 任何第一个兄弟元素的通配符路由器插座

router-outlet + * {
  // your rules
}

对我来说,它有助于将路由器插座包装到另一个容器中。

<div class="classYouWantApplied">
  <router-outlet>
</div>

像这样,您可以将 class 应用于周围的容器。

添加主机 class 名称,这将向组件添加 class,然后使用 adjacent 定位元素。

@Component({
  selector:'project',
  host: {
      class:'Project-wrapper'
  }
})

现在使用 CSS 与 angular

相邻
::ng-deep to target it:
::ng-deep .Project-wrapper {}

很简单,假设在您的应用组件中有一个
<router-outlet ></router-outlet>

在此 router-outlet 中,您有一个名为 <app-product-detail></app-product-detail>

并且您想更改 app.component.html 中的视图。

首先在组件内部 <app-product-detail> 添加此代码段:

@Component({


selector: 'app-product-detail',
  host: {
    class:'Project-wrapper'
},
  templateUrl: './product-detail.component.html',
  styleUrls: ['./product-detail.component.css']
})```

class='could be any name'

在 app.component.css 中添加以下代码段:

    ::ng-deep .Project-wrapper { 
width: 85%;
        background-color: aqua;
    }