当我尝试迭代 ngFor 循环时,Angular 2+ attr.disabled 不适用于 div
Posted
技术标签:
【中文标题】当我尝试迭代 ngFor 循环时,Angular 2+ attr.disabled 不适用于 div【英文标题】:Angular 2+ attr.disabled is not working for div when I try to iterate ngFor loop 【发布时间】:2017-12-28 14:13:15 【问题描述】:我正在开发一个预约应用程序,我正在使用 *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
而不是禁用,它工作得很好。但问题是我想显示时隙是否可用。
【问题讨论】:
你能检查一下时间段的所有状态是否都是真的吗? (console.log(this.allTimeSlots)
在 for 循环之后),如果是,那么问题在于您如何检查时隙
我检查了它,即使 item.status 仅用于调试目的。它打印出我给它的正确值 true 和 false。但它在 [attr.disabled] 中不起作用
好的,我创建了一个plunker here 来演示您描述的问题,我现在会尝试看看如何解决它:)
是的,完全一样的事情发生在我身上,我已经编辑了问题并在其中添加了我的截图,从中可以更好地理解它。 @0mpurdy
你可以试试this answer给出的语法。
【参考方案1】:
使用[disabled]
而不是[attr.disabled]
这是因为[attr.disabled]="false"
会将disabled="false"
添加到 html 中的元素中,仍然会禁用该元素
不会禁用元素的语法
<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 类来显示预订的时间段。
有关[ngClass]
的更多信息,请访问the documentation
【讨论】:
@user2136053 那么你肯定也会喜欢这个: [attr.disabled]="isDisabled ? '' : null" (注意内部的 '' 是 2 个单引号) 派对迟到了,但我认为 [disabled]="false" 不会禁用该元素。但是 [attr.disabled]="false" 确实如此。【参考方案2】:正如 0mpurdy 回答的那样,您应该使用 [disabled] 属性。变量不必是布尔值,但表达式应该是。
在您的代码中,它确定 item.status 是虚假的还是真实的。因此,如果它不是 null/NaN/undefined,您将获得“true”并且 div 将被禁用。
改为插入表达式:
[disabled]="item.status === 'occupied'"
编辑
对不起,我错过了。 由于您无法禁用 div,因此请将 disabled 属性放在输入标签内。
<input type="radio" [disabled]="item.status === 'occupied'" name="slot" value="item.timeSlot">
由于您想将选择显示为禁用,您需要将其直接放在输入中。单选按钮将无法点击,并且会显示“光标:不允许”。
希望有帮助
【讨论】:
我尝试了所有这些方法。但 [disabled] 不适用于 div 元素。 感谢您的贡献!截至目前,我正在使用div
元素来完成radio
的工作,我只需要禁用div
。上面批准的答案对我来说很有效。【参考方案3】:
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;
【讨论】:
不适合我。给出错误 => 未捕获的错误:模板解析错误:无法绑定到“已禁用”,因为它不是“div”的已知属性。 (" 应该指出,该解决方案不会像通常使用 disabled 属性的情况那样阻止在该元素上触发 click 事件? @Jacques 如果你不希望点击事件触发添加pointer-events:none
【参考方案4】:
这样使用:
[attr.disabled]="isDisabled ? '' : null"
只读也是如此。
【讨论】:
如果你已经有 Reactive Forms 的逻辑,那将会覆盖。 这就是我想要的。角度不同【参考方案5】:CSS
.disabled-contenct
pointer-events: none;
opacity: 0.4;
HTML
<div [class.disabled-contenct]="!isDisabledContent"></div>
TS
isDisabledContent: boolean;
那么您可以随时切换 isDisabledContent。
【讨论】:
【参考方案6】:Attribute 指令肯定会帮助您禁用或启用 div 或任何其他 HTML 元素及其子元素。
禁用指令
首先,创建一个属性指令,它将一个参数 (appDisable) 作为输入。它将根据输入禁用/启用 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);
不要忘记在 AppModule 中注册 DisableDirective
如何在组件中使用指令? 在组件的指令中传递布尔值(true/false)。
<div class="container" [appDisable]="true">
</div>
您可以参考完整的帖子HERE
在Stackblitz上运行示例
【讨论】:
【参考方案7】:有一种方法可以使用attribute binding。这是一个简单的方法。实现方法见the docs。
【讨论】:
以上是关于当我尝试迭代 ngFor 循环时,Angular 2+ attr.disabled 不适用于 div的主要内容,如果未能解决你的问题,请参考以下文章
如何使用包含键作为字符串和值作为映射迭代的ngFor循环映射进行迭代