【问题标题】:Why does toggling one checkbox also toggle some others?为什么切换一个复选框也会切换其他一些复选框?
【发布时间】:2020-05-13 22:10:42
【问题描述】:

我构建了一个表格组件。用户可以选择他想看的列。

您可以在 StackBlitz 上试用。没有所有 SCSS 看起来并不好看,但它显示了相同的现象。 https://stackblitz.com/edit/angular-she4fk

一开始,只勾选了三个复选框,并且相应的列是可见的。

当我切换任何一个复选框时,该列会显示或隐藏,其他复选框也会被选中/取消选中。列显示正确,但复选框完全错误。我没有看到问题,特别是因为表和底层数组的行为符合预期!

对于此示例,我从 Frame 1 开始,其中 First nameSur nameDepartment 列可见(并选中了相应的复选框)。然后我设置Selection 复选框:开-关-开。每次,其他复选框都会做出反应(没有更改底层数组)。

我想知道为什么。最重要的是:我怎样才能阻止其他盒子做出反应? (也许有趣的旁注:模式是可重现的。当我重新加载应用程序 (F5) 并选择 Selection 复选框时,我总是可以重现这些完全相同的“第 1-4 帧”。所以其他复选框的行为不是随机的.)

这是代码,非常简单。

export class AppComponent  {
    fieldTitle: string[] = [];
    fieldVisibility: boolean[] = [];

    constructor()
    {
        this.fieldTitle[0] = 'Selection';
        this.fieldTitle[1] = 'Personal number';
        this.fieldTitle[2] = 'Salutation';
        this.fieldTitle[3] = 'First name';
        this.fieldTitle[4] = 'Last name';
        this.fieldTitle[5] = 'Department';
        this.fieldTitle[6] = 'Company';

        this.fieldVisibility[0] = false;
        this.fieldVisibility[1] = false;
        this.fieldVisibility[2] = false;
        this.fieldVisibility[3] = true;
        this.fieldVisibility[4] = true;
        this.fieldVisibility[5] = true;
        this.fieldVisibility[6] = false;
    }

    toggleVisibility(fieldIdx: number) {
        console.log(fieldIdx + ' BEFORE toggle: ' + JSON.stringify(this.fieldVisibility));
        this.fieldVisibility[fieldIdx] = !this.fieldVisibility[fieldIdx];
        console.log(fieldIdx + ' AFTER  toggle: ' + JSON.stringify(this.fieldVisibility));
    }

    isVisible(fieldIdx: number) {
        console.log(fieldIdx + ' is ' + (this.fieldVisibility[fieldIdx] ? 'visible' : 'hidden'));
        return this.fieldVisibility[fieldIdx];
    }
}

还有模板:

<table>
    <tr>
        <ng-container *ngFor="let visible of fieldVisibility; index as i;">
            <th *ngIf="visible">{{fieldTitle[i]}}</th>
        </ng-container>

        <th>
            <ul>
                <!-- solution: "let dummy of fieldTitle; index as i" -->
                <li *ngFor="let visible of fieldVisibility; index as i">
                    <label>
                        <input (change)="toggleVisibility(i)"
                              [checked]="isVisible(i)"
                              type="checkbox">
                        {{fieldTitle[i]}}
                    </label>
                </li>
            </ul>
        </th>
    </tr>
</table>

【问题讨论】:

  • 可以在stackblitz中提供代码吗?
  • 看起来这个代码(change)="fieldVisibility[i] = !fieldVisibility[i]" 是多余的。能否请您评论并检查它
  • @SatishPai 你可以在angular-obmnmw.stackblitz.io 找到它。当我删除(change) 时,当然切换一个复选框不会切换任何其他复选框。但相应的表格列也不会显示/隐藏。
  • angular-obmnmw.stackblitz.io 这个链接是托管的,我想处理源代码。可以提供一下链接吗?
  • @SatishPai 啊,对不起。我第一次使用 StackBlitz。 stackblitz.com/edit/angular-obmnmw 从“托管链接”到“编辑链接”似乎很简单。 :-)

标签: angular


【解决方案1】:

*ngFor 中使用fieldTitle 数组,而不是fieldVisibility。像这样: &lt;ng-container *ngFor="let visible of fieldTitle; index as i"&gt;

【讨论】:

  • 你能告诉我为什么会这样吗?
  • @Anarno 谢谢,这行得通。但是我也有兴趣了解为什么会有所作为?当然,不要更改循环的inside *ngFor 使用的数组是有意义的。但是话又说回来,我不是在更改数组,而是在更改数组内部的值。我会争辩说,这 应该 工作 --- 并且使用 fieldTitle 而不是 should not 有所作为。嗯,确实如此。 :-) 但是为什么呢?
  • 数组是一个对象。如果对象发生变化,则角度重新渲染 DOM。永远不要更改可变对象。或者使用trackBy whit 一个独特的id 属性,然后角度知道哪些行发生了变化,并且只重新渲染变化的行。
  • 在浏览器中查看检查,查看 DOM 中的列表,当你使用 fieldVisibility 数组时,你会看到它是如何工作的。
【解决方案2】:

如果你迭代,你不能迭代你想要改变的相同元素

<ng-container *ngFor="let visible of [0,1,2,3,4,5,6]; let i=index">

你没有问题。即使您决定只有一个独特的数组,例如

fields=[
      {title: 'Selection',visibility:false},
        {title: 'Personal number',visibility:false},
        {title: 'Salutation',visibility:false},
        {title: 'First name',visibility:true},
        {title: 'Last name',visibility:true},
        {title: 'Department',visibility:true},
        {title: 'Company',visibility:false}
    ]

你可以的

<ng-container *ngFor="let field of fields; index as i;">
    <th *ngIf="field.visibility">{{fieldTitle[i]}}</th>
</ng-container>

(看到我们可以使用 field.visibility 和 field.title)

<input [(ngModel)]="field.visibility"
    [name]="'fieldSelectId'+i" 
    class="form-check-input" [id]="'fieldSelect'+i" type="checkbox" >

在这种情况下,您不会违反“不能迭代您更改的元素”的规则,因为您更改的是对象的“属性”,而不是对象本身

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-07
    • 2018-12-19
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    • 2017-01-03
    • 1970-01-01
    相关资源
    最近更新 更多