当我尝试迭代 ngFor 循环时,Angular 2+ attr.disabled 不适用于 div

Angular 2+ attr.disabled is not working for div when I try to iterate ngFor loop

我正在开发一个约会应用程序,我在其中使用 *ngFor 循环显示约会的时间段。

html

<div *ngFor="let item of allTimeSlots">
    <div class="col-sm-3">
        <div class="choice" data-toggle="wizard-slot" [attr.disabled]="item.status" (click)="slotSelected($event)">
            <input type="radio" name="slot" value="{{item.timeSlot}}">
            <span class="icon">{{item.timeSlot}}</span> {{item.status}}
        </div>
    </div>
</div>

打字稿

for (var index = 0; index < this.totalMinutes; index += 15, i++) {
  this.allTimeSlots[i] = new allTimeSlots("", false);

  this.allTimeSlots[i].timeSlot = (hour <= 12 ? hour : hour - 12) + ":" + (minute <= 9 ? ("0" + minute) : minute) + " " + ampm;
  this.bookedTimeSlots.forEach(element => {
    if (this.allTimeSlots[i].timeSlot == element) {
      this.allTimeSlots[i].status = true;
    }
  });
}

这是时间段的屏幕截图,如果时间段已预订,则显示 true,如果可用于调试目的,则显示 false。

当我 运行 此代码时,它不会抛出任何错误,但 *ngFor 创建的所有 div 元素都被禁用。我尝试使用 *ngIf 而不是禁用,效果很好。但是问题是我想显示时间段是否可用

使用[disabled]代替[attr.disabled]

这是因为 [attr.disabled]="false" 将向 html 中的元素添加 disabled="false",但仍会禁用该元素

不会禁用元素的语法

<button>Not Disabled</button>
<button [disabled]="false">Not Disabled</button>

将禁用元素的语法

<button disabled></button>
<button disabled="true"></button>
<button disabled="false"></button>
<button [attr.disabled]="true"></button>
<button [attr.disabled]="false"></button>
<button [disabled]="true"></button>

disabled 将禁用一个元素,无论它是真还是假,它的存在意味着该元素将被禁用。如果 variable 为假,Angular 将不会为 [disabled]="variable" 添加 disabled 元素。

正如您在评论中提到的,您使用的是 div 元素而不是按钮,angular 2 无法识别其中的禁用元素。如果您要捕获 click 事件,我建议您使用按钮,但如果不是,您可以执行以下操作:

<div [ngClass]="{ 'disabled': item.status }"></div>

并有一个 CSS class 来显示已预订的时间段。

有关 [ngClass] 的更多信息,请参阅 the documentation

正如 0mpurdy 所回答的那样,您应该使用 [disabled] 属性。变量不必是布尔值,但表达式应该是。

在您的代码中,它确定 item.status 是假的还是真实的。因此,如果它不是 null/NaN/undefined,您将得到“true”并且 div 将被禁用。

而是插入一个表达式:

[disabled]="item.status === 'occupied'"


编辑

抱歉我错过了。 由于您无法禁用 div,因此请将禁用的属性放入输入标签中。

<input type="radio" [disabled]="item.status === 'occupied'" name="slot" value="{{item.timeSlot}}">

由于您想将选择显示为已禁用,因此需要将其直接放在输入中。单选按钮将不可点击,并且将显示 'cursor: not-allowed'。

希望对您有所帮助

Disabled 不能用于 div 元素,只能应用于以下元素

<button>    
<fieldset>  
<input> 
<keygen>    
<optgroup>  
<option>    
<select>    
<textarea>  

See this

所以对于你的问题,你可以通过以下方式处理:

<div 
  class="choice" 
  data-toggle="wizard-slot" 
  [class.disabled]="item.status" 
  (click)="slotSelected($event)">
  <input 
    type="radio" 
    name="slot" 
    value="{{item.timeSlot}}" 
    [disabled]="item.status">
  <span class="icon">{{item.timeSlot}}</span> {{item.status}}
</div>

你应该添加样式

.disabled {
  cursor: not-allowed;
}

这样使用:

[attr.disabled]="isDisabled ? '' : null"

同样适用于只读。

CSS

.disabled-contenct {
  pointer-events: none;
  opacity: 0.4;
}

HTML

<div [class.disabled-contenct]="!isDisabledContent"></div>

TS

isDisabledContent: boolean;

然后您可以随时切换 isDisabledContent。

属性指令肯定会帮助您禁用或启用 div 或任何其他 HTML 元素及其子元素。

DisableDirective

首先,创建一个将一个参数 (appDisable) 作为输入的属性指令。它将根据输入 disable/enable DOM 元素及其子 DOM 元素。

import { AfterViewInit, Directive, ElementRef, Input, OnChanges, Renderer2 } from '@angular/core';

const DISABLED = 'disabled';
const APP_DISABLED = 'app-disabled';
const TAB_INDEX = 'tabindex';
const TAG_ANCHOR = 'a';

@Directive({
  selector: '[appDisable]'
})
export class DisableDirective implements OnChanges, AfterViewInit {

  @Input() appDisable = true;

  constructor(private eleRef: ElementRef, private renderer: Renderer2) { }

  ngOnChanges() {
    this.disableElement(this.eleRef.nativeElement);
  }

  ngAfterViewInit() {
    this.disableElement(this.eleRef.nativeElement);
  }

  private disableElement(element: any) {
    if (this.appDisable) {
      if (!element.hasAttribute(DISABLED)) {
        this.renderer.setAttribute(element, APP_DISABLED, '');
        this.renderer.setAttribute(element, DISABLED, 'true');

        // disabling anchor tab keyboard event
        if (element.tagName.toLowerCase() === TAG_ANCHOR) {
          this.renderer.setAttribute(element, TAB_INDEX, '-1');
        }
      }
    } else {
      if (element.hasAttribute(APP_DISABLED)) {
        if (element.getAttribute('disabled') !== '') {
          element.removeAttribute(DISABLED);
        }
        element.removeAttribute(APP_DISABLED);
        if (element.tagName.toLowerCase() === TAG_ANCHOR) {
          element.removeAttribute(TAB_INDEX);
        }
      }
    }
    if (element.children) {
      for (let ele of element.children) {
        this.disableElement(ele);
      }
    }
  }
}

Do not forget to register DisableDirective in the AppModule

如何在组件中使用指令?
在组件的指令中传递布尔值 (true/false)。

<div class="container" [appDisable]="true">
</div>

你可以参考完整的PostHERE

运行 Stackblitz

示例

有一种方法可以使用 attribute binding. It is a simple method. See the docs 如何实施。