@在Angular中使用变量类进行HostBinding

@在Angular中使用变量类进行HostBinding,angular,Angular,我有一个在主机上设置类的代码: @HostBinding('class.fixed') true; 我想做的是使它成为一个可以修改的变量类。 我怎样才能做到这一点?这不能变为变量 您可以做的是直接绑定到class属性 @HostBinding('class') classes = 'class1 class2 class3'; 如果类的数量有限,则可以有条件地添加每个类: @HostBinding('class.c1') get c1 () { return this.useC1; } @

我有一个在主机上设置类的代码:

@HostBinding('class.fixed') true;
我想做的是使它成为一个可以修改的变量类。
我怎样才能做到这一点?

这不能变为变量

您可以做的是直接绑定到class属性

@HostBinding('class') classes = 'class1 class2 class3';

如果类的数量有限,则可以有条件地添加每个类:

@HostBinding('class.c1') get c1 () { return this.useC1; } 
@HostBinding('class.c2') get c2 () { return this.useC2; }
请注意,
.c1
.c2
需要在组件外部定义


我不得不反驳其他答案,没有理由认为绑定
class.foo
不起作用。实际上,以下格式工作正常:

@HostBinding('class.foo') variableName = true;
如果它在您的情况下不起作用,您可能需要向CSS类添加一个作用域(您可以看到一个讨论)

问题是,
HostBinding
只查看主机作用域,这意味着它只查看应用于组件本身的类和id,而不查看其子级。因此,在编写CSS时,需要指定CSS属于组件本身(宿主伪元素)

根据:

使用:host伪类选择器以承载组件的元素中的样式为目标(而不是以组件模板中的元素为目标)

只需在CSS规则之前添加
:host
,即可轻松指定主机范围:

:host.foo { // It only matches <Component class="foo">
  /* Your CSS here */
}
:host.foo{//它只匹配
/*你的CSS在这里*/
}
代替

.foo { // It matches any <element class="foo" /> inside <Component>
  /* Your CSS here */
}
.foo{//它匹配任何内部
/*你的CSS在这里*/
}

如果您愿意,我创建了一个工作的Plunk,您可以看到它。

您可以使用类创建一些单独的指令

例如:我的页面中有一个按钮,可能有以下状态:
默认
主要
危险
流体
。按钮可以有许多不同的状态,但由于代码量巨大,我将向您展示这三种状态。让我们开始吧

按钮。ts

//default button

@Directive({
    selector: '[appButtonDefault]'
})
export class ButtonDefaultDirective {

    // the name of the field is not important
    // if you put this directive to element, 
    // this element will have the class called 'button--default'

    @HostBinding("class.button--default")
    private defaultClass: boolean = true;
}


//primary button

@Directive({
    selector: '[appButtonPrimary]'
})
export class ButtonPrimaryDirective {

    // the name of the field is not important
    // if you put this directive to element, 
    // this element will have the class called 'button--primary'

    @HostBinding("class.button--primary")
    private primaryClass: boolean = true;
}


// danger button

@Directive({
    selector: '[appButtonDanger]'
})
export class ButtonDangerDirective {

    // the name of the field is not important
    // if you put this directive to element, 
    // this element will have the class called 'button--primary'

    @HostBinding("class.button--danger")
    private dangerClass: boolean = true;
}

@Directive({
    selector: '[appButtonFluid]'
})
export class ButtonFluidDirective {

    // the name of the field is not important
    // if you put this directive to element, 
    // this element will have the class called 'button--primary'

    @HostBinding("class.button--fluid")
    private fluidClass: boolean = true;
}


// you need to also create a component class,
// that import styles for this button
@Component({
    //just put created selectors in your directives
    selector: `[appButtonDefault], [appButtonPrimary], 
               [appButtonDanger], [appButtonFluid]`,
    styleUrls: ['<-- enter link to your button styles -->'],

    // it is required, because the content of <button> tag will disappear
    template: "<ng-content></ng-content>" 
})
export class ButtonComponent {}


// you don't have to do it, but I prefet to do it

@NgModule({
    declarations: [
        ButtonDefaultDirective,
        ButtonPrimaryDirective,
        ButtonDangerDirective,
        ButtonFluidDirective,
        ButtonComponent
    ],
    exports: [
        ButtonDefaultDirective,
        ButtonPrimaryDirective,
        ButtonDangerDirective,
        ButtonFluidDirective,
        ButtonComponent
    ]
})
export class ButtonModule {}

我希望这会有所帮助。

Günter的答案对于已经将一些类名绑定到变量的情况来说并没有真正的帮助

将变量字符串类名与布尔样式预定义类名相结合的一个好方法是使用npm包

将其与
@HostBinding
和setter函数一起使用,可以获得令人惊讶的结果:

import*作为“classNames”中的类名;
(...)
@HostBinding('class')获取类():字符串{
返回类名(this.getDynamicClassName(){
“已打开”:this.isOpen,
“has children”:this.has children
});
}

您可以使用输入劫持class属性,并将所需内容添加到hostbinding中

已经有很多答案,但没有一个提到
NgClass
。 在我看来,最可靠和一致的方法是扩展
NgClass
,因为它提供了我们所需的一切:

@Directive({ selector: '[myDirective]'})
export class MyDirective extends NgClass {
  constructor(
    _iterableDiffers: IterableDiffers,
    _keyValueDiffers: KeyValueDiffers,
    _ngEl: ElementRef,
    _renderer: Renderer2
  ) {
    super(_iterableDiffers, _keyValueDiffers, _ngEl, _renderer);
  }

  setClass() {
    this.ngClass = {
      underline: true,
      bold: true,
      italic: true,
      pretty: false
    };

    // or
    this.ngClass = ['asd', 'abc', 'def'];

    // or 
    this.ngClass = 'foo';
  }
}

反对票投给谁?没用吗?从那以后发生了一些变化,导致绑定到
[class]=“…”
时出现问题,这可能也会影响这种方法。先生,您是生命的救星!这是可行的,但问题是它会覆盖从父元素添加到宿主元素的任何类component@GünterZöchbauer,这个问题是在GitHub的某个地方提出的吗?你能分享这个问题的链接吗?@GünterZöchbauer-我已经创建了一个问题()-将看到它的进展。我需要添加
()
,它才能工作(例如
get c1(){return this.useC1;}
。如果使用
:host
选择器,则不需要在组件外部定义
.c1
.c2
。请参阅此答案的示例:对我来说,在方法名称之前添加“get”关键字后,它就起作用了。谢谢:)我认为
(.className)周围不需要括号
将其链接时
:主机
。我想你们做的链子和其他选择线一样<代码>:host.className这是一个固定的类名,而不是一个可变的类名。我希望在您的生产代码中没有使用这种方法。。。大量代码而不是一行…这是一个很好的答案,以更好的方式解决了IMHO问题,对于这个问题的未来访问者来说,上面问题中的代码片段只适用于Angular中的一个bug,该bug将在未来版本中修复:
@Input()
  class = '';

@HostBinding('attr.class')
get btnClasses() {
return [
    'btn',
    this.someClassAsString,
    this.enableLight ? 'btn-secondary-light' : '',
    this.class,
].filter(Boolean).join(' ');
};
@Directive({ selector: '[myDirective]'})
export class MyDirective extends NgClass {
  constructor(
    _iterableDiffers: IterableDiffers,
    _keyValueDiffers: KeyValueDiffers,
    _ngEl: ElementRef,
    _renderer: Renderer2
  ) {
    super(_iterableDiffers, _keyValueDiffers, _ngEl, _renderer);
  }

  setClass() {
    this.ngClass = {
      underline: true,
      bold: true,
      italic: true,
      pretty: false
    };

    // or
    this.ngClass = ['asd', 'abc', 'def'];

    // or 
    this.ngClass = 'foo';
  }
}