【问题标题】:How to create independent instances of one angular component如何创建一个角度组件的独立实例
【发布时间】:2019-12-28 01:23:26
【问题描述】:

我正在尝试在 Angular 中创建一个简单的组件,该组件基本上将枚举映射到单选按钮输入。我已经设置并工作了,但是当我将该组件的多个实例放在一个页面上时,我遇到了一些奇怪的问题。我看到的是组件的两个副本相互反应。

这是针对使用 Angular 8 的项目。我已将代码分解为托管在此处的一个小项目,以便您查看发生了什么。托管组件是 app.component.html/.ts,单选按钮组件是 radio.component.html/.ts。

https://stackblitz.com/edit/angular-rcurne

编辑以在此处添加一些实际代码

app.component.html

<app-radio
  [radioSelection]="selectionRadio1"
  (radioSelectionChange)="selectionRadio1 = $event"
></app-radio>
<label>Radio Option Selected: {{ selectionRadio1.toString() }}</label>
<br />
<br />
<app-radio
  [radioSelection]="selectionRadio2"
  (radioSelectionChange)="selectionRadio2 = $event"
></app-radio>
<label>Radio Option Selected: {{ selectionRadio1.toString() }}</label>

radio.component.html

<div class="form-check">
  <input
    class="form-check-input"
    type="radio"
    name="radioInput"
    id="radioInput1"
    [value]="radioSelectionType.Option1"
    [(ngModel)]="radioSelection"
    (ngModelChange)="radioSelectionChangedByUser($event)"
  />
  <label class="form-check-label" for="radioInput1">Option 1</label>
</div>
<div class="form-check">
  <input
    class="form-check-input"
    type="radio"
    name="radioInput"
    id="radioInput2"
    [value]="radioSelectionType.Option2"
    [(ngModel)]="radioSelection"
    (ngModelChange)="radioSelectionChangedByUser($event)"
  />
  <label class="form-check-label" for="radioInput2">Option 2</label>
</div>
<div class="form-check">
  <input
    class="form-check-input"
    type="radio"
    name="radioInput"
    id="radioInput3"
    [value]="radioSelectionType.Both"
    [(ngModel)]="radioSelection"
    (ngModelChange)="radioSelectionChangedByUser($event)"
  />
  <label class="form-check-label" for="radioInput3">Both</label>
</div>

radio.component.ts

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { RadioSelectionType } from './RadioSelectionType'

@Component({
  selector: 'app-radio',
  templateUrl: './radio.component.html'
})
export class RadioComponent implements OnInit {
  @Input() radioSelection: RadioSelectionType;
  @Output() radioSelectionChange = new EventEmitter<RadioSelectionType>();
  public radioSelectionType = RadioSelectionType;

  constructor() { }

  ngOnInit() {
    // If no default was specified via the input, default to Option 3
    if (!this.radioSelection) {
      this.radioSelection = RadioSelectionType.Option3;
    }
  }

  radioSelectionChangedByUser(value: RadioSelectionType) {
    this.radioSelectionChange.emit(this.radioSelection);
  }

}

如上所述,我看到无线电输入会相互反应,即使它们是独立的组件。也请随意批评我的编码选择 - 我是一名 C# 开发人员,最近开始使用 Angular,所以我可能会遗漏一些关于它如何在网络上工作的内容。

【问题讨论】:

    标签: javascript html angular typescript components


    【解决方案1】:

    这是一个基于您的代码的工作示例:https://angular-4dsvdv.stackblitz.io

    组件实例是独立的:一个组件实例看不到同类型的另一个组件实例的变量。在这种情况下,您违反了 RadioButton 组的 W3C 规则。您可以通过为所属的单选按钮赋予相同的名称属性值来创建单选按钮组。如果将标签与单选按钮相关联,则标签“for”属性必须包含相关单选按钮的 id。 ID 在 DOM 树中必须是唯一的。

    如果您的页面上有两个组件实例,您的收音机组件的 HTML sn-p 将在您页面的 DOM 树中复制。两个单选按钮组具有相同的组名,并且单选按钮的 ID 不是唯一的。您可以通过提供唯一的按钮组名称作为输入值(或在组件中动态创建)并动态创建唯一的单选按钮 ID 来解决此问题。标签的“for”属性也需要指向这些动态 id。

    DOM 应该如下所示: enter image description here

    【讨论】:

      【解决方案2】:

      我还可以通过添加一个包裹在我的组件周围的 &lt;form&gt; 标签来解决这个问题,如下所示:

      <form>
        <div class="form-check">
          <input
            class="form-check-input"
            type="radio"
            name="radioInput"
            id="radioInput1"
            [value]="radioSelectionType.Option1"
            [(ngModel)]="radioSelection"
            (ngModelChange)="radioSelectionChangedByUser($event)"
          />
          <label class="form-check-label" for="radioInput1">Option 1</label>
        </div>
        <div class="form-check">
          <input
            class="form-check-input"
            type="radio"
            name="radioInput"
            id="radioInput2"
            [value]="radioSelectionType.Option2"
            [(ngModel)]="radioSelection"
            (ngModelChange)="radioSelectionChangedByUser($event)"
          />
          <label class="form-check-label" for="radioInput2">Option 2</label>
        </div>
        <div class="form-check">
          <input
            class="form-check-input"
            type="radio"
            name="radioInput"
            id="radioInput3"
            [value]="radioSelectionType.Both"
            [(ngModel)]="radioSelection"
            (ngModelChange)="radioSelectionChangedByUser($event)"
          />
          <label class="form-check-label" for="radioInput3">Both</label>
        </div>
      </form>
      

      【讨论】:

        【解决方案3】:

        广播组应该有唯一的名称。在您的代码中,所有单选按钮具有相同的名称。

        解决方案:将名称作为输入属性传递将解决问题

          ...
          export class RadioComponent implements OnInit {
             @Input() name: string;
             ...
        

        模板:

        ...
        <div class="form-check">
          <input
            class="form-check-input"
            type="radio"
            [name]="name"
        ...
        

        // app.component.html

        <h1>Hello, world!</h1>
        <app-radio
        name="r1"
          [radioSelection]="selectionRadio1"
          (radioSelectionChange)="selectionRadio1 = $event"
        ></app-radio>
        <label>Radio Option Selected: {{ selectionRadio1.toString() }}</label>
        <br />
        <br />
        <app-radio
        name="r2"
          [radioSelection]="selectionRadio2"
          (radioSelectionChange)="selectionRadio2 = $event"
        ></app-radio>
        <label>Radio Option Selected: {{ selectionRadio2.toString() }}</label>
        

        https://stackblitz.com/edit/angular-bxp4my

        【讨论】:

          猜你喜欢
          • 2019-01-17
          • 1970-01-01
          • 1970-01-01
          • 2012-03-27
          • 2022-10-15
          • 2017-03-12
          • 2013-12-06
          • 2012-08-27
          • 2023-02-10
          相关资源
          最近更新 更多