【问题标题】:Add events to elements after the DOM has been created创建 DOM 后向元素添加事件
【发布时间】:2016-02-04 19:38:33
【问题描述】:

我试图弄清楚在元素添加到 DOM 后如何向元素添加事件。

现在,我有这样的事情:

import {Component} from 'angular2/core';

@Component({
    selector   : 'sub-child',
    template   : '<form [innerHTML]="html"></form>'
})

export class SubChildClass
{
    private html:string;
    private buttonText:string;

    constructor()
    {
        this.buttonText = 'A new button';
        this.create();
    }

    private create()
    {
        this.html = "<button (click)='new()'>" + this.buttonText + "</button>"
    }

    private new()
    {
        this.buttonText = "Text Changed";
    }
}

不起作用的部分是:

this.html = "<button (click)='new()'>" + this.buttonText + "</button>"

此时,Angular 2 不知道如何处理 (click)='new()'。我不确定这样做的正确方法是什么。

我希望以后能够通过一些相应的事件将 HTML 添加到 DOM。

我没有使用过 Angular 1。但听起来这曾经相当于 $compile in Angular 1。其他一些帖子建议使用Dynamic Content Loader 处理此类内容。但这似乎不是这个用例的正确答案。因此,感谢任何帮助或指导。谢谢,

【问题讨论】:

  • 为什么不直接在模板中添加按钮? angular 2 的想法是你尽量避免自己创建 dom 对象,让 angular 为你做这件事。你将你想要的组件直接添加到模板中,如果你想以动态方式显示或出现,你可以使用*ngIf="flag" 之类的东西来告诉他什么时候渲染,什么时候不渲染。
  • 就像我提到的,Angular 中的想法是在模板中定义这些动态元素,并通过使用诸如ngIf、ngFor、ngClass 之类的结构属性,您可以更改它们的外观或行为。因此,您的逻辑会更改模型,并且视图会对这些更改做出反应。如果您展示您的真实案例,可能会更容易告诉您执行此操作的“角度方式”是什么。如果您真的想自己创建它们,请查看:angular.io/docs/ts/latest/api/core/ElementRef-class.html 并确保您阅读了警告,以免错过。
  • “我希望以后能够通过一些相应的事件将 HTML 添加到 DOM” 是的,但是您的示例中的代码不是 HTML,它的 Angular 模板语法angular.io/docs/ts/latest/guide/template-syntax.html .
  • Angular 并不是为了这样使用而设计的,所以即使有可能它也不会像正确的方式那样简单。您可能必须自己控制事件:angular.io/docs/ts/latest/api/core/EventEmitter-class.html 在没有真实案例的情况下无法说出真正的答案,在您发布的示例中,解决方案是将代码添加到模板中。
  • 我必须强烈同意@Langley 的观点。这真的不是解决这个问题的好方法,sigh...我已经发布了一个可能的例子但是正如你所看到的,当你降到这个级别时,你会失去很多。实际上,您最好只在 angular2 组件内用 jQuery 编写站点或表单并以 jQuery 方式控制它。请花一些时间考虑考虑这个问题的替代方案或其他方式,您可能会使用嵌套组件或其他方式找到更好的解决方案。

标签: angular typescript


【解决方案1】:

更新建议

import {Component} from '@angular/core';

@Component({
  selector: 'special-button-component',
  template: '<button type="button" (click)="changeText()">{{buttonText}}</button>'
})
export class SpecialButtonComponent{
  public buttonText: string = 'A New Button';
  public changeText(): void{
    this.buttonText = 'Text Changed';
  }
}

@Component({
  selector   : 'sub-child',
  template   : '<form><special-button-component></special-button-component></form>'
})
export class SubChildClass{}

原始答案 (由于从 Angular 2 中删除了 BrowserDomAdapter,因此不再工作)

如果您真的想要绑定到已注入的非模板 DOM 元素,那么您可以使用 Angular2 的一些相当无证的功能以良好的“老式方式”设置事件侦听器

import {Component, ElementRef} from 'angular2/core';
import {BrowserDomAdapter} from 'angular2/platform/browser';

@Component({
  selector   : 'sub-child',
  template   : '<form [innerHTML]="html"></form>'
})
export class SubChildClass
{
  private html:string;
  private buttonText:string;

  constructor(private elementRef: ElementRef, private domAdapter: BrowserDomAdapter)
  {
    this.buttonText = 'A new button';
    this.create();
  }

  private create()
  {
    let button = this.domAdapter.createElement('button');
    button.innerHtml = this.buttonText;
    this.domAdapter.on(button, 'click', this.new.bind(this));
    this.domAdapter.appendChild(this.elementRef.nativeElement, button);
  }

  private new()
  {
    let button = this.domAdapter.querySelector(this.elementRef.nativeElement, 'button');
    button.innerHTML = "Text Changed";
  }
}

但是有什么意义...如果我们只是降到这个级别,为什么要首先使用角度。我还在生产中的企业应用程序中使用 Angular2。我对此功能的选择是将button 本身创建为一个组件,然后使用DynamicComponentLoader 将元素注入。

【讨论】:

  • 感谢您的回复。将按钮创建为组件是一个有趣的想法。因此,假设我创建了一个由文本区域、输入、按钮、链接等以任何给定顺序组成的表单。您认为最好的方法是将它们中的每一个都视为一个组件并根据需要将它们注入到我的应用程序中?
  • 对于一般性答案,可能是的,尽管它可能取决于您的用例。
  • 我对“routerLink”有同样的问题。请看我的问题:stackoverflow.com/q/37421007/1579102
  • @SnareChops 你知道 BrowserDomAdapter 在 Angular 2.0.0-rc.4 中移动到哪里了吗?
  • @Katana24 我的理解是它已被删除以支持使用Renderer
【解决方案2】:

我使用 ngFor 来重复 DOM。当您按下单击按钮时,将项目添加到数组中。例子: + 组件:

export class AbcComponent {
  billingInforArr: RegisterBillingInfoModel[] = [];

  months: any[] = [];
  years: any[] = [];

  constructor(private fb: FormBuilder, private router: Router) {
    for (let i = 1; i <= 12; i++) {
      this.months.push({ value: i, text: i });
    }

    let today = new Date();
    let year = today.getFullYear();
    for (let i = 1; i <= 10; i++) {
      this.years.push({ value: year + i, text: year + i });
    }

    if (localStorage.getItem('listCard') != null) {
      this.billingInforArr = JSON.parse(localStorage.getItem('listCard'));
    }
  }
  addCard(value: any) {
    this.billingInforArr.push({ Id: Date.now().toString(), NameOnCard: value.name, CardNumber: value.cardNumber, ExpMonth: value.expMonth, ExpYear: value.expYear, Expire: `${value.expMonth}/${value.expYear}` });
    localStorage.setItem('listCard', JSON.stringify(this.billingInforArr));
  }
  removeCard(value: any) {
    console.log(value);
    console.log(this.billingInforArr);

  }
}
  • HTML:

<div class="form-group list-credit" *ngFor="let item of billingInforArr">
  <div class="content-credit">
    <i class="material-icons remove" (click)="removeCard(item.Id)">cancel</i>
  </div>
</div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-29
    • 1970-01-01
    • 2020-11-02
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    相关资源
    最近更新 更多