【问题标题】:How to add "class" to host element?如何将“类”添加到宿主元素?
【发布时间】:2016-04-11 00:35:41
【问题描述】:

我不知道如何在我的组件<component></component> 中添加一个动态的class 属性,但在模板html (component.html) 中。

我找到的唯一解决方案是通过“ElementRef”原生元素修改项目。这个解决方案似乎有点复杂,做一些应该很简单的事情。

另一个问题是 CSS 必须在组件范围之外定义,破坏了组件封装。

有没有更简单的解决方案?模板中的 <root [class]="..."> .... </ root> 之类的东西。

【问题讨论】:

    标签: angular angular2-template


    【解决方案1】:

    这就是我所做的:

    import { Component, Attribute, HostBinding } from "@angular/core";
    
    @Component({
        selector: "selector-el",
        template: ...                                            
    })
    export class MyComponent {
        @HostBinding('class') get classAttribute(): string {
            let defaultClasses = 'selector-el-class';
            return defaultClasses + ' ' + this.classNames;
        }
    
        constructor(
            @Attribute('class') public classNames: string
        ) { }
    }
    

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    【解决方案2】:

    除了@JoshuaDavid 的回答,还有另一种定义静态类的方法,当我尝试时它适用于角度 v8(可能也适用于旧版本):

    @Component({
    selector: "my-component.someClass1.someClass2",
    ...
    })
    

    这将产生以下输出:

    <my-component class="someClass1 someClass2">
     ...
    </my-component>
    

    你也可以这样使用:

    @Component({
    selector: ".someClass1.someClass2",
    ...
    })
    

    这将产生以下输出:

    <div class="someClass1 someClass2">
     ...
    </div>
    

    【讨论】:

    • 如果我指定selector: "my-component.someClass1.someClass2",,那么我必须在 HTML 中使用选择器,例如 ...
    【解决方案3】:

    这样你就不需要在组件之外添加CSS了:

    @Component({
       selector: 'body',
       template: 'app-element',
       // prefer decorators (see below)
       // host:     {'[class.someClass]':'someField'}
    })
    export class App implements OnInit {
      constructor(private cdRef:ChangeDetectorRef) {}
      
      someField: boolean = false;
      // alternatively also the host parameter in the @Component()` decorator can be used
      @HostBinding('class.someClass') someField: boolean = false;
    
      ngOnInit() {
        this.someField = true; // set class `someClass` on `<body>`
        //this.cdRef.detectChanges(); 
      }
    }
    

    Plunker example

    这个 CSS 是在组件内部定义的,只有当 someClass 类设置在宿主元素上时才会应用选择器(从外部):

    :host(.someClass) {
      background-color: red;
    }
    

    【讨论】:

    • 我必须在ngOnInit()-方法中使用someField = true 而不是ngAfterViewInit()。否则我无法让它工作。
    • Made a fork here 显示实际的:host 部分工作。我在哪里可以了解更多关于 @Component() 装饰器中的主机参数(语法对我来说并不明显,以及 @Component documentation doesn't explain very much)或了解更多关于您首选的 HostBinding(它只是 Angular2 站点上的 listed as an Interface?)
    • 我不知道更好的文档,但这只是用 @Input() @Output() @HostBinding() @HostListener() @ViewChild(ren)() @ContentChild(ren)() 做的另一种方式>
    • 对主机绑定使用不同名称的getter,返回反转值@HostBinding('class.xxx') get xxxclass(){ return !this.someField;}
    • @YochaiAkoka 不确定您指的是什么。我不知道这个规则。少即是多,所以如果你能避免添加额外的元素,那么你应该避免它。
    【解决方案4】:

    另一个问题是 CSS 必须在组件范围之外定义,破坏了组件封装

    这不是真的。使用 scss (SASS),您可以轻松地设置组件(本身;主机)的样式:

    :host {
        display: block;
        position: absolute;
        width: 100%;
        height: 100%;
        pointer-events: none;
        visibility: hidden;
    
        &.someClass {
            visibility: visible;
        }
    }
    

    这样封装是“完整的”。

    【讨论】:

    • 由于其他答案有不同的方式为您的组件设置类,如果您使用这种方式,您可以将您的类设置为组件上的类。因此,对于此答案中的示例,它将是:
    【解决方案5】:

    对于多类的情况,就像上面提到的@jbojcic,你可以使用:

    主机:{类:'A B C'}

    【讨论】:

      【解决方案6】:

      您可以在 @Component 类中简单地添加@HostBinding('class') class = 'someClass';

      例子:

      @Component({
         selector: 'body',
         template: 'app-element'       
      })
      export class App implements OnInit {
      
        @HostBinding('class') class = 'someClass';
      
        constructor() {}      
      
        ngOnInit() {}
      }
      

      【讨论】:

      • className directive 也可以使用,最好避免使用class 作为变量名(因为您可能会引用它并在以后更改它)。示例:@HostBinding('className') myTheme = 'theme-dark';.
      • 我肯定会避免将变量命名为“类”。一些包将其命名为“klass”或“cssClass”
      【解决方案7】:

      如果你想为你的宿主元素添加一个动态类,你可以将你的 HostBinding 与一个 getter 结合起来

      @HostBinding('class') get class() {
          return aComponentVariable
      }
      

      Stackblitz 演示,https://stackblitz.com/edit/angular-dynamic-hostbinding

      【讨论】:

        【解决方案8】:

        Günter 的回答很棒(问题是要求 dynamic 类属性),但我想我只是为了完整性而添加...

        如果您正在寻找一种快速而简洁的方法来将一个或多个 static 类添加到组件的宿主元素(即,出于主题样式目的),您可以这样做:

        @Component({
           selector: 'my-component',
           template: 'app-element',
           host: {'class': 'someClass1'}
        })
        export class App implements OnInit {
        ...
        }
        

        如果你在 entry 标签上使用了一个类,Angular 会合并这些类,即,

        <my-component class="someClass2">
          I have both someClass1 & someClass2 applied to me
        </my-component>
        

        【讨论】:

        • 为了简单起见喜欢这个。但是在我的情况下,主机元素被封装了一个不同的属性,我们称它为ngcontent_host,而不是我的组件的模板, let's call those ngcontent_template, so if I put a style in the styleUrls`中的元素上的任何属性,它们不会影响主机元素,因为它们不会影响 ngcontent_host ,它们只能影响模板元素;它们只能影响ngcontent_template。我弄错了吗?对此有何建议?我想我总是可以转ViewEncapsulation.None
        • 另一种方法是跳过变量@HostBinding('class.someClass') true;。您甚至可以从您的组件扩展的任何类中执行此操作。
        • 添加多个类你可以做 host: { '[class]': '"class1 class2"' }
        • 如果您使用主机:{} 变体,您可能希望在tslint.json 中将use-host-property-decorator 设置设置为false。否则,您将收到 IDE 警告。 @adamdport 该方法不起作用(不再)。在我们的应用中使用 Angular 5.2.2。
        • @adamdport 您的回答将创建一个名为“true”的变量,类型为“any”。不确定这是否是您的意图?
        【解决方案9】:

        我是这样做的(Angular 7):

        在组件中,添加一个输入:

        @Input() componentClass: string = '';
        

        然后在组件的 HTML 模板中添加如下内容:

        <div [ngClass]="componentClass">...</div>
        

        最后在您实例化组件的 HTML 模板中:

        <root componentClass="someclass someotherclass">...</root>
        

        免责声明:我对 Angular 还很陌生,所以我可能只是在这里走运!

        【讨论】:

        猜你喜欢
        • 2017-01-31
        • 1970-01-01
        • 2018-05-12
        • 2018-06-21
        • 2023-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多