Angular-使用Render2在Angular组件中动态设置属性指令

时间:2019-06-05 11:24:07

标签: angular typescript angular-directive

我在我的应用程序中创建了一个组件,用作输入标签的包装器(我在制作自己的UI库很有趣)。我的组件将像这样使用。

<sio-input [label]="'Sio Input Label'">
        <input type="text" name="">
</sio-input>

这样做的目的是动态添加CSS类和功能,因此开发人员不必这样做。这是我的组件(为了便于阅读,我已经按比例缩小了代码)

@Component({
  selector: 'sio-input',
  templateUrl: './input.component.html', // only contains <ng-content></ng-content>
  styleUrls: ['./input.component.scss'],

})
export class InputComponent implements OnInit {

  @Input() label: string;
  // this component used Render2 - https://angular.io/api/core/Renderer2
  constructor(private elRef: ElementRef, private renderer: Renderer2) {
  }

  ngOnInit() {
    // if a label exist prepend it to the HTML
    if (this.label) {
      const formInput = this.elRef.nativeElement.querySelector('input');
      const appendLabel = this.renderer.createElement('LABEL');
      const textNode = this.renderer.createText(this.label);
      this.renderer.addClass(appendLabel, 'sio-input__label');
      this.renderer.appendChild(appendLabel, textNode);
      this.renderer.insertBefore(this.elRef.nativeElement, appendLabel, formInput);

      // add the directive
      this.renderer.setAttribute(formInput, 'sioInput', null);
    }
  }
}

@Directive({
  selector: '[sioInput]'
})
export class SioInputDirective {
  @HostListener('focus', ['$event.target'])
  onFocus(event) {
    console.log('Boom! We Have Focus');
  }
}

如您所见,我希望向在组件DOM中找到的formInput动态添加属性指令。遗憾的是,这无法正常工作,因为renderer.setAttribute呈现的输出采用了“ sioInput”属性名称并将其呈现为“ sioinput”,因此Angular无法识别该属性指令。我是否应该在输入中的模板HTML中手动放置指令名称,自然一切正常-但我希望它是动态的。我究竟做错了什么?如何在不将名称转换为小写的情况下动态设置属性指令。

在此先感谢您-如果我不能很好地解释我的问题或感到困惑,请这样说,我将重述我的问题。

1 个答案:

答案 0 :(得分:0)

Angular是一种编译语言:您编写TS,将其转换为JS。

装饰器中的选择器是构建前:不能在构建后中应用。

这意味着您不应使用渲染器(它将执行 post-build ),而应使用模板本身来管理角度组件。

作为旁注,组件中的指令通常是组件使用@ContentChild通过<ng-content>管理内容的一种方式。除了将自定义类添加到elementRef中,以及可能实现控件值访问器之外,该指令并没有做什么用。

我建议您看看Material Input ElementsPrimeNG来了解它们的用法,因为它们被广泛使用并且通常也很容易使用!