Inject Style Declarations Using Hostbinding in Angular

左心房为你撑大大i 提交于 2019-11-28 01:11:38

问题


Do you guys know how I can batch inject style declarations in a component using the @HostBinding decorator? What I am trying is:

@HostBinding('style')
get style(): CSSStyleDeclaration {
  return {
    background: 'red',
    color: 'lime'
  } as CSSStyleDeclaration;
}

In my understanding this should inject the background and color style to the component, but it does not...

I can control individual style declarations like this:

@HostBinding('style.background') private background = 'red';

but I would like to do it for all of them, please help :P

this is the full code:

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello world!</h2>
    </div>
  `,
})
export class App {

  // This works
  @HostBinding('style.color') private color = 'lime';

  /* This does not work
  @HostBinding('style')
  get style(): CSSStyleDeclaration {
    return {
      background: 'red'
    } as CSSStyleDeclaration;
  }
  */

  constructor() {}
}

and a working plunker: https://plnkr.co/edit/CVglAPAMIsdQjsqHU4Fb?p=preview


回答1:


You need to pass the same value you would add to an element like <div style="..."> and sanitize the styles

  @HostBinding('style')
  get myStyle(): SafeStyle {
    return this.sanitizer.bypassSecurityTrustStyle('background: red; display: block;');
  }

  constructor(private sanitizer:DomSanitizer) {}

working demo




回答2:


Here is a solution that can cover if you want to pass multiple css styles as string or as object with cammelCase conventions:

Parent HTML

<app-button [style]="styleFromParent">Some button</app-button>

Parent component has styleFromParent property and it has simulation if that property is changed at some point:

Parent Component TS

import { Component, OnInit, ChangeDetectorRef } from '@angular/core';

@Component({
  selector: 'app-site-panel',
  templateUrl: './site-panel.component.html',
})
export class SitePanelComponent implements OnInit {
  constructor(private _detectChanges: ChangeDetectorRef) {}
  styleFromParent = { marginTop: '10px', marginLeft: '50px' };

  ngOnInit() {
    setTimeout(() => {
      this.styleFromParent = { marginTop: '20px', marginLeft: '1px' };

      this._detectChanges.detectChanges();
    }, 2000);
  }
}

Child HTML

<ng-content></ng-content>

Child Component TS

import { Component, OnInit, HostBinding, Input } from '@angular/core';
import { DomSanitizer, SafeStyle } from '@angular/platform-browser';

@Component({
  selector: 'app-button',
  templateUrl: './button.component.html',
})
export class ButtonComponent implements OnInit {
  @HostBinding('style') baseStyle: SafeStyle;

  @Input()
  set style(style: string | object) {
    let mappedStyles = style as string;

    if (typeof style === 'object') {
      mappedStyles = Object.entries(style).reduce((styleString, [propName, propValue]) => {
        propName = propName.replace(/([A-Z])/g, matches => `-${matches[0].toLowerCase()}`);
        return `${styleString}${propName}:${propValue};`;
      }, '');

      this.baseStyle = this.sanitizer.bypassSecurityTrustStyle(mappedStyles);
    } else if (typeof style === 'string') {
      this.baseStyle = this.sanitizer.bypassSecurityTrustStyle(mappedStyles);
    }
  }

  constructor(private sanitizer: DomSanitizer) {}

  ngOnInit() {}
}

Above you can see that baseStyle has HostBinding to style component binding. When style input is passed setter will triger, check if string or object is passed, parse it to string and sanitize that css and assign it to baseStyle thus host style will change.



来源:https://stackoverflow.com/questions/46150788/inject-style-declarations-using-hostbinding-in-angular

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!