简体   繁体   English

在运行时分配Angular结构指令

[英]Assigning Angular structural directives during runtime

I am trying to assign *ngIf directive from angular code to the template during runtime. 我试图在运行时将角度代码的* ngIf指令分配给模板。 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. view / templateref是一个选项吗?或者有一个不同的方式和一个更容易的方式。 Is it possible in the first place? 有可能首先吗?

Update: 更新:

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. 但是这里是DOM代码的外观,以及为什么我需要动态添加内置结构指令。

<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>

Update 更新

I am doing a fetch request based on userProvidedValue value and the result of the fetch request decides the fetchArraywithHttpFromuserProvidedValue array. 我正在根据userProvidedValue值执行获取请求,并且获取请求的结果决定了fetchArraywithHttpFromuserProvidedValue数组。 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. 其次,根据从获取请求派生的fetchArraywithHttpFromuserProvidedValue的值,决定是否在switch选项中显示用户提供的模板或预定的模板集。 (only part of user provided template needs the *ngIf directive. The user template is parsed in JS to get the needed part). (只有部分用户提供的模板需要* ngIf指令。用户模板在JS中解析以获取所需的部分)。 The use case is similar to a tool that creates a HTML design/page which fetches structure from a user. 该用例类似于创建从用户获取结构的HTML设计/页面的工具。 This is exactly for a similar tool, just that I am not making a tool that creates a user defined HTML page. 这正是一个类似的工具,只是我没有创建一个创建用户定义的HTML页面的工具。

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. 如果这是不可能的,那么请推荐一个替代方案,允许我类似地分配功能或在这种情况下让我解决方法。

Update 2 更新2

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: 如下面的一个答案所指出的,以下所有模板都无法使用elementref或使用ViewContainerRef + TemplateRef进行正确的解析/编译:

<input [value]="someVariableFromClass"/>

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

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

The following works though, if the template is in the DOM before the application is being built and loaded (not dynamic addition): 但是,如果在构建和加载应用程序之前模板位于DOM中(而不是动态添加),则以下方法有效:

<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>

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. 目前,我正在Angular中尝试编译器API并检查compileModuleAndAllComponentsAsync<T>(moduleType: Type<T>): Promise<ModuleWithComponentFactories<T>>可以帮助我解决这个用例。 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). 问题似乎是我将通过将html作为模板分配给组件来创建一个全新的组件,然后创建一个动态模块,然后在插入视图之前编译整个(逻辑我正在尝试当前 - 不工作然而)。 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. 看起来我最终可能会将静态指令添加到手动占位符并添加[innerHTML]= / safeHTML / Sanitize API ,如果我没有成功的话。 Not ideal though. 虽然不太理想。 Please help with alternatives if you can. 如果可以,请帮助替代方案。

I am using this example, though it's plunkr currently not working. 我正在使用这个例子,虽然它的plunkr目前无法正常工作。

How can I use/create dynamic template to compile dynamic Component with Angular 2.0? 如何使用/创建动态模板来使用Angular 2.0编译动态组件?

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

You don't call a fetch method inside an *ngIf. 你没有在* ngIf中调用fetch方法。 The ... inside *ngIf="..." gets executed every time angular decides to do change-detection and that might be dozens of times per second. 每当角度决定进行变化检测时,......内部*ngIf="..."内部执行,并且可能每秒数十次。 You don't want to deploy a DDOS for your own backend. 您不希望为自己的后端部署DDOS。

This is why you should put a field like isUserProvidedValueValid there and update that field in the subscription of your HttpClient-call: 这就是为什么你应该在那里放置一个像isUserProvidedValueValid这样的字段并在你的HttpClient调用的订阅中更新该字段的原因:

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;
      });
}

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 您可以使用指令内的管道(您不需要使用ng-template ,使用普通标签的innerHtml),如下例所示: https ://stackoverflow.com/a/39858064/4125622

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

Or before the .subscribe() in the code above, you can do 或者在上面代码中的.subscribe()之前,你可以做到

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

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. 如果你需要转换这个代码,你可以添加另一个.map() - RXJS-mapper或另一个自定义管道 - 这取决于你喜欢哪种变换器。 In the transformer you can use VanillaJS for manipulation of the user-code. 在变换器中,您可以使用VanillaJS来操纵用户代码。 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. 也许HTML-parser-plugin或JSON-toHTML-parser-plugin或类似的东西可能对您有用 - 取决于您的用户提供的数据类型。

No you can't add structure directives dynamically, you need to approach it by thinking what is your app expecting later on. 不,你不能动态地添加结构指令,你需要通过思考你的应用程序在以后期待什么来接近它。

For example, if you plan on looping through an array which I'm guessing is what you intend to do having looked at your code, you could do the following: 例如,如果您计划循环遍历数组,我猜测的是您打算查看代码,您可以执行以下操作:

hotels: any;

<div *ngIf="hotels.length > 0">
  <div *ngFor="let item of hotels">{{item.name}}</div>
</div>

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM