我创建了一个具有许多输入属性的自定义组件.然而,我在使用这个组件时注意到的一点是,父组件中的许多输入属性是相同的.

示例用法如下所示:

<yes-no
 controlName="isAwesome"
 labelKeyBase="MODULE.PAGE_X"
 validationKeyBase="VALIDATION.CUSTOM_X"
 someOtherProp="true"
></yes-no>

我一直在使用一个名为transloco的库,并注意到一些功能在这种情况下非常有用.不幸的是,我不知道它将如何实施.

https://ngneat.github.io/transloco/docs/translation-in-the-template#utilizing-the-read-input

我想知道是否有一个简化的示例演示了如何将值从父指令传递给子组件.基本上,我的目标是将上述代码转换为以下内容:

<ng-container *yesNoConfig="labelKeyBase: 'MODULE.PAGE_X'; validationKeyBase: 'VALIDATION.CUSTOM_X'">
 <yes-no controlName="isAwesome"></yes-no>
 <yes-no controlName="isClean"></yes-no>
 <yes-no controlName="isShort"></yes-no>
</ng-container>

推荐答案

以下是一个将任意属性应用于容器的所有直接子级的指令:

@Directive({
  selector: '[setAttributes]',
})
export class SetAttributesDirective {
  @Input('setAttributes') atts: { [key: string]: string } = {};

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef
  ) {}

  ngOnInit() {
    const keys = Object.keys(this.atts);
    const viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
    for (const node of viewRef.rootNodes) {
      if (typeof node.setAttribute !== 'function') continue;
      const el = node as HTMLElement;
      for (const key of keys) el.setAttribute(key, this.atts[key]);
    }
  }
}

不是很安全,因为viewRef.rootNodesany[],但你能做什么…我放了一个防打字.第一个条目实际上是ng-container本身,嵌套的模板/ng容器也没有setAttribute函数,在没有typeguard的情况下抛出错误.当然可以改进,但至少你知道要点.

你可以这样使用它:

<ng-container *setAttributes="{ type: 'number', value: '5', min: '0', max: '10' }">
  <input />
  <input />
  <input />
  <input />
</ng-container>

关联单据:https://angular.io/guide/structural-directives

Stackblitz示例:https://stackblitz.com/edit/angular-ivy-1eyjlo?file=src/app/app.component.html


对于您的示例,您需要从DOM node 获取组件实例.有一个用于调试的函数,但不确定为什么它不是常规API的一部分:https://angular.io/api/core/global/ngGetComponent

您必须告诉tsc该函数存在,然后您可以设置组件的属性:

declare global {
  interface Window {
    ng: { getComponent: (el: Element) => { [key: string]: any } | null };
  }
}

@Directive({
  selector: '[setInputs]',
})
export class SetInputsDirective {
  @Input('setInputs') atts: { [key: string]: any } = {};

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef
  ) {}

  ngOnInit() {
    const keys = Object.keys(this.atts);
    const viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
    for (const node of viewRef.rootNodes) {
      if (!(node instanceof Element)) continue;
      const component = window.ng.getComponent(node);
      if (component === null) continue;
      for (const key of keys) component[key] = this.atts[key];
    }
  }
}
<ng-container *setInputs="{ labelKeyBase: 'MODULE.PAGE_X', validationKeyBase: 'VALIDATION.CUSTOM_X' }">
 <yes-no controlName="isAwesome"></yes-no>
 <yes-no controlName="isClean"></yes-no>
 <yes-no controlName="isShort"></yes-no>
</ng-container>

Stackflash:https://stackblitz.com/edit/angular-ivy-mbcw9o?file=src/app/app.component.html

Angular相关问答推荐

如何在Angular模块中的forRoot中注入配置

Angular 动画—淡出适用于DIV,不完全适用于子组件

带有搜索功能的CDK-VIRTUAL-SCROLL-VIEPORT不显示该值

按Angular 从组件的 bootstrap 选项卡中删除活动类

无效的ICU消息.缺少';}';|Angular material 拖放(&A)

PrimeNg选项卡视图选项卡

AOS-如何在向上滚动时不再次隐藏元素

当在server.ts文件中定义API路径时,Angular 17构建失败

出错后可观察到的重用

Angular CLI 与 Angular 版本不兼容

RxJs 中的空闲可观察对象在幕后做了什么?

等待两个订阅完成而不嵌套

尽管模型中的变量发生了变化,但Angular 视图没有更新

全局异常处理

Angular2 测试 - 按 ID 获取元素

Angular CLI 自定义 webpack 配置

如何处理解析器中的错误

Angular 2 Material - 如何居中进度微调器

Angular2延迟加载模块错误'找不到模块'

如何防止角material垫菜单关闭?