简体   繁体   English

Typescript和Angular:将字符串键入组件类

[英]Typescript and Angular: Type a string to a component class

a function is passing the name of my component via a string but I need it to be the actual component class: 一个函数通过字符串传递组件的名称,但是我需要它成为实际的组件类:

Current: "MyComponent" Need: MyComponent 当前:“ MyComponent”需要:MyComponent

I need to "convert" it so It's passing correctly. 我需要对其进行“转换”,以便正确传递。 I have an ngFor that spits out values and I'm trying to use piping to convert it: 我有一个ngFor ,它吐出值,并且我试图使用管道将其转换:

<div id="grid">
    <gridster [options]="options">
    <gridster-item [item]="item" *ngFor="let item of dashboard;let i = index;">
      <div class="grid-header drag-handle">
        <span class="handle-icon"><i class="material-icons">open_with</i></span>
        <span class="close-icon" (click)="removePanel(item)"><i class="material-icons">close</i></span>
      </div>
      <div class="grid-content">
        <ndc-dynamic [ndcDynamicComponent]="item.viewType | dynamicComponent"></ndc-dynamic>
      </div>
    </gridster-item>
  </gridster>
</div>

Above it's item.viewType that's a strong coming from my item array. 在它上面的item.viewType是我的item数组的强项。 I'm passing the value to a dynamicComponent custom pipe. 我将值传递给dynamicComponent自定义管道。 I have my components imported into my dynamic-component.pipe.ts . 我将组件导入到dynamic-component.pipe.ts I just need to change the string to the specified viewType and return the typed value: 我只需要将字符串更改为指定的viewType并返回typed值:

import { Pipe, PipeTransform } from '@angular/core';
//pulling in all the possible components
import * from '../../views';

@Pipe({
  name: 'dynamicComponent'
})
export class DynamicComponentPipe implements PipeTransform {

  transform(value: string): any {


  }

}

You'll need to manually create a mapping between string values and the components. 您需要手动在字符串值和组件之间创建映射。 Components are actually named functions which can be minimized to shorter variable names when compiling for production. 组件实际上是命名函数,在进行生产编译时可以将其最小化为较短的变量名。

import ComponentA from '../views/ComponentA'; 
import ComponentB from '../views/ComponentA';

const componentMap = {
    'ComponentA': ComponentA,
    'ComponentB': ComponentB
};

@Pipe({name: 'dynamicComponent'})
export class DynamicComponentPipe implements PipeTransform {
   transform(value: string): any {
       if(componentMap[value]) {
          return componentMap[value];
       }
       throw new Error(`${componentMap} component was not found`);
   }
}

UPDATED: 更新:

The problem with using the name of a component at runtime is that it can be minimized into a smaller variable name for production. 在运行时使用组件名称的问题在于,可以将其最小化为较小的变量名称以进行生产。 Therefore, doing something like views['MyComponent'] won't work later when MyComponent is renamed to something like a12 . 因此,将MyComponent重命名为a12东西之后,执行诸如views['MyComponent']将无法正常工作。

An alternative approach is to use the component's selector string value to select the component. 另一种方法是使用组件的选择器字符串值选择组件。 Each component in Angular has to be a unique selector string. Angular中的每个组件都必须是唯一的选择器字符串。 So this is a safe value to use as a key. 因此,这是用作密钥的安全值。

You can access (at least in Angular 5) the component's metadata via the __annotations__ property. 您可以通过__annotations__属性访问(至少在Angular 5中)组件的元数据。 This property is an array that contains a the metadata. 此属性是一个包含元数据的数组。

So you could try something like: 因此,您可以尝试执行以下操作:

import * as views from '../views';

@Pipe({name: 'dynamicComponent'})
export class DynamicComponentPipe implements PipeTransform {
   transform(value: string): any {
       const view = views.filter((component)=>component['__annotations__'][0]['selector'] === value));
       if(view) {
          return view;
       }
       throw new Error(`A component with selector "${value}" was not found`);
   }
}

Furthermore, you could drop the need for a views file by accessing the ngModule directly and iterating all components to find a matching selector. 此外,您可以通过直接访问ngModule并迭代所有组件以找到匹配的选择器来减少对views文件的需求。 Modules will have the same __annotations__ property. 模块将具有相同的__annotations__属性。

I did this pretty simple way: 我这样做很简单:

I created a views.ts with all of my views exported at the root of my views directory. 我创建了一个views.ts并将所有视图导出到我的views目录的根目录。 Then in directory that my pipe is being used I imported the views using: 然后在使用管道的目录中,使用以下命令导入views

import * as views from '../../views/views'

Then in my transform method I return views[value]; 然后,在我的transform方法中,我return views[value]; where value is the string being pulled in from my template. 其中value是从模板中提取的字符串。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 TypeScript 中使用抽象 class 作为 React 组件的类型? - How to use an abstract class as the type of a React component in TypeScript? 根据 Typescript Angular 中的类型为类实例属性分配一个值 - Assign class instance property a value based on its type in Typescript Angular 如何从Angular 2应用程序中的TypeScript / JavaScript中的字符串中获取类? - How to get a class from a string in TypeScript/JavaScript in an Angular 2 application? 字符串值的打字稿+ angular2通过类 - typescript + angular2 pass class from a string value 从Typescript / Angular2中的类字符串创建实例 - Create instance from class string in Typescript/Angular2 Typescript - 使用类型扩展 class - Typescript - Extending class with type 我想在 Angular 中添加局部变量,但出现错误“type 'string null' is not assignable to type 'string'. typescript” - I want to add local variable in Angular but error occur "type 'string null' is not assignable to type 'string'. typescript" Angular2 / TypeScript:错误TS2345:类型'String'的参数不能分配给'string'类型的参数 - Angular2/TypeScript: error TS2345: Argument of type 'String' is not assignable to parameter of type 'string' 使用 ref 键入 React 组件? 打字稿 - Type React component with ref? Typescript Typescript 样式组件错误:“类型 '{ children: string; }' 没有与类型 'IntrinsicAttributes' 相同的属性。” - Typescript styled-component error: "Type '{ children: string; }' has no properties in common with type 'IntrinsicAttributes'."
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM