在运行时分配Angular结构指令 [英] Assigning Angular structural directives during runtime

查看:104
本文介绍了在运行时分配Angular结构指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在运行时将角度代码中的* ngIf指令分配给模板.无法找到一种方法来做到这一点.是view/templateref的一种选择,还是有不同的方法和更简单的方法.首先有可能吗?

I am trying to assign *ngIf directive from angular code to the template during runtime. Not been able to figure out a way to do it. Is view/templateref an option to do it or is there a different way and an easier one. Is it possible in the first place?

更新:

代码有点混乱和混乱,因此请避免使用.但是这里是DOM代码,它看起来大致如何,为什么我需要动态添加内置的结构指令.

The code is a little messy and jumbled, so avoided it. But here is the DOM code how it approximately looks and why I need to add inbuilt structural directives dynamically.

<div>
  <input type="text" [value]="userProvidedValue">
  <textarea [value]="someDynamicDOMCodefromWYSIWYG">
    <!-- user provided provided code or dynamic code -->
  </textarea>
</div>
<div>
  <select *ngIf="fetchArraywithHttpFromuserProvidedValue">
    <option *ngFor="let val of fetchArraywithHttpFrom-userProvidedValue" value=""></option>
  </select>
</div>
<div>
  <ng-template>
    <!-- Some User provided code or dynamic code which might need to use *ngIf OR *ngFor -->
    <!-- The *ngIf OR *ngFor will be added dynamically based on a manipulator function which is decided from the value of fetchArraywithHttpFromuserProvidedValue -->
  </ng-template>
</div>

更新

我正在基于 userProvidedValue 值进行获取请求,并且获取请求的结果决定了 fetchArraywithHttpFromuserProvidedValue 数组.其次,根据从提取请求中获取的 fetchArraywithHttpFromuserProvidedValue 的值,决定是在switch选项中显示用户提供的模板还是预定的模板集.(仅用户提供的模板的一部分需要* ngIf指令.用户模板在JS中进行解析以获取所需的部分).用例类似于创建HTML设计/页面的工具,该工具从用户那里获取结构.这恰好是针对类似工具的,只是我不是要创建可创建用户定义的HTML页面的工具.

Update

I am doing a fetch request based on userProvidedValue value and the result of the fetch request decides the fetchArraywithHttpFromuserProvidedValue array. Second, based on the value of fetchArraywithHttpFromuserProvidedValue derived from fetch request the decision is made whether to show the user provided template or a predecided set of templates in switch option. (only part of user provided template needs the *ngIf directive. The user template is parsed in JS to get the needed part). The use case is similar to a tool that creates a HTML design/page which fetches structure from a user. This is exactly for a similar tool, just that I am not making a tool that creates a user defined HTML page.

请帮助我.如果无法做到这一点,那么请推荐一种替代方法,该方法可以让我类似地分配功能,或者在这种情况下获得解决方法.

Please help me out with this. If this is not possible, then please recommend an alternative that will allow me to assign functionality similarly or get me a workaround in this situation.

就像在以下答案之一中指出的那样,以下所有模板均无法通过使用elementref或使用ViewContainerRef + TemplateRef进行正确的解析/编译来添加:

Like pointed out in one of the answers below, all of the following templates failed to be added with proper parsing/compilation with elementref or using ViewContainerRef + TemplateRef:

<input [value]="someVariableFromClass"/>

<input value="{{someVariableFromClass}}"/>

<div *ngFor="let item of items">{{item}}</div>

但是,如果模板在构建和加载应用程序之前位于DOM中(不是动态添加),则可以使用以下内容:

The following works though, if the template is in the DOM before the application is being built and loaded (not dynamic addition):

<ng-template #tpl>
  <!-- Add the template to #vcr using ViewContainerRef from the class -->
    <div *ngFor="let item of items">{{item}}</div>
</ng-template>
<div #vcr>
    <!-- Add the template from #tpl using ViewContainerRef from the class -->
</div>

目前,我正在尝试Angular中的编译器API,并检查 compileModuleAndAllComponentsAsync< T>(moduleType:Type< T>):Promise< ModuleWithComponentFactories< T>> 是否可以帮助我用例.问题似乎是我将通过将html作为模板分配给组件来创建一个全新的组件,然后创建一个动态模块,然后在插入视图之前编译整个组件(我目前正在尝试的逻辑-无法正常工作然而).此后(如果成功的话),我将尝试使用指令添加组件模板,并查看编译是否正确.欢迎任何帮助.如果我不成功,看来我可能最终会通过向手动占位符添加静态指令并添加 [innerHTML] =/safeHTML/Sanitize API 来结束.虽然不理想.如果可以的话,请提供其他替代方法.

Currently, I am trying out the compiler API in Angular and checking if compileModuleAndAllComponentsAsync<T>(moduleType: Type<T>): Promise<ModuleWithComponentFactories<T>> can help me in this use case. The issue seems like I will have a create a completely new component by assigning the html as a template to the component, then create a dynamic module, and then compile the whole before inserting into the view (Logic I am trying out currently - not working yet). After this (if I succeed), I will try adding the component template with a directive and see if that compiles right. Any help is welcome. It seems like I might end up by adding static directives to manual placeholders and adding [innerHTML]= / safeHTML / Sanitize API, if I dont succeed. Not ideal though. Please help with alternatives if you can.

我正在使用此示例,尽管它目前无法正常运行.

I am using this example, though it's plunkr currently not working.

我如何使用/创建动态模板以使用Angular 2.0编译动态组件?

http://plnkr.co/edit/wh4VJG?p=preview

推荐答案

您不要在* ngIf内部调用fetch方法.每次angular决定进行更改检测时, * ngIf ="..." 中的...都会执行,每秒可能会发生数十次.您不想为自己的后端部署DDOS.

You don't call a fetch method inside an *ngIf. The ... inside *ngIf="..." gets executed every time angular decides to do change-detection and that might be dozens of times per second. You don't want to deploy a DDOS for your own backend.

这就是为什么您应该在其中放置 isUserProvidedValueValid 之类的字段并在HttpClient调用的订阅中更新该字段的原因:

This is why you should put a field like isUserProvidedValueValid there and update that field in the subscription of your HttpClient-call:

userProvidedValue: any;
isUserProvidedValueValid: boolean = false;

constructor(private httpClient: HttpClient) {}

doFetch() { // called by a button-click for example
    this.isUserProvidedValueValid = false;
    this.httpClient
      .get<any>(SOME_URL)
      .subscribe(res => {
          if (res) { // you might have a complex check here, not just not-undefined
               this.isUserProvidedValueValid = true;
          }
          // you might consider putting this in the if-clause and in the *ngIf only check for userProvidedValue being not null
          this.userProvidedValue = res;
      });
}

现在输入用户提供的代码:首先,您需要对其进行清理.您可以使用指令内的管道来执行此操作(无需使用 ng-template ,您可以使用常规标签的innerHtml),例如以下示例:

Now for the code that your user provides: first of all, you need to sanitize it. You can do it with a pipe inside a directive (you don't need to use ng-template, you use innerHtml of a normal tag for it) like in this example: https://stackoverflow.com/a/39858064/4125622

  template: `<div [innerHtml]="html | safeHtml"></div>`,

或者在以上代码中的.subscribe()之前,您可以进行

Or before the .subscribe() in the code above, you can do

// domSanitizer needs to be injected in constructor as well
.map(res => this.domSanitizer.bypassSecurityTrustHtml(res)); 

如果需要转换此代码,则可以添加另一个.map()-RXJS-mapper或另一个自定义管道-由您决定是哪种类型的转换器.在转换器中,您可以使用VanillaJS来处理用户代码.也许HTML-parser-plugin或JSON-toHTML-parser-plugin或类似的东西可能对您有用-取决于用户提供的数据类型.

If you need to transform this code, you can add another .map()-RXJS-mapper or another custom pipe - it's up to you which kind of transformer you prefer. In the transformer you can use VanillaJS for manipulation of the user-code. Perhaps an HTML-parser-plugin or a JSON-toHTML-parser-plugin or something similar might be useful to you - depends on the data type your user provides.

这篇关于在运行时分配Angular结构指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆