我在angular2应用程序中有一个materialize可折叠列表。我想要做的是,当有人点击它时,更改列表项的图标。到目前为止,我将一个click事件附加到列表中。当我将其打印到控制台时,我看到了元素参考。所以我能够查看子节点并找到附加了活动类的li元素。我的想法是,一旦找到活动元素,我就可以将子节点的图标更改为新图标。这样我就不会改变所有的图标。但是,当我尝试将图标设置为新图标时,我得到TypeError: 0 is read-only
。有没有人知道如何通过角度2来做到这一点?
Plunker
https://plnkr.co/edit/jQWf7uIRZIwr4fhyFT03?p=preview
列表
<ul class="collapsible" data-collapsible="accordion">
<li>
<div class="collapsible-header"><i class="material-icons">filter_drama</i>First</div>
<div class="collapsible-body"><span>Lorem ipsum dolor sit amet.</span></div>
</li>
<li>
<div class="collapsible-header"><i class="material-icons">place</i>Second</div>
<div class="collapsible-body"><span>Lorem ipsum dolor sit amet.</span></div>
</li>
<li>
<div class="collapsible-header"><i class="material-icons">whatshot</i>Third</div>
<div class="collapsible-body"><span>Lorem ipsum dolor sit amet.</span></div>
</li>
</ul>
所需行为: 基本上我正在尝试使用materlize可折叠列表制作下拉树。因此,您单击某个项目,将其图标从加号更改为减号,以模拟您正在扩展和收缩该项目。
答案 0 :(得分:6)
您可以使用您在点击时更改的变量在两个图标之间切换:
class Program
{
static void Main(string[] args)
{
Mapper.Initialize(MapperConfiguration);
var parent = new Parent()
{
Id = "a",
Child = new Child()
{
Name = "ChildA",
Id = 1
}
};
var child = Mapper.Map<Child>(parent);
Console.Read();
}
private static void MapperConfiguration(IMapperConfigurationExpression mapper)
{
mapper.CreateMap<Parent, Child>()
.ProjectUsing(x => x.Child);
}
public class Parent
{
public string Id { get; set; }
public Child Child { get; set; }
}
public class Child
{
public string Name { get; set; }
public int Id { get; set; }
}
}
如果您只想隐藏图标,只需使用一个图标即可:
<div class="collapsible-header" (click)="showFirst=!showFirst"><i class="material-icons" *ngIf="showFirst">filter_drama</i><i class="material-icons" *ngIf="!showFirst">place</i>First Section</div>
我分叉你的plunker并编辑了变化here
PS:在您的plunker上,您正在从<div class="collapsible-header" (click)="showSecond=!showSecond"><i class="material-icons" *ngIf="!showSecond">place</i>Second Section</div>
网址加载材质图标,使Chrome无法加载资源。将网址更改为http
即可。
@Judson Terrell - 对我来说,Angular唯一的解决方案看起来更干净
https
<强> HTML 强>
<div class="collapsible-header" (click)="!show=show"><i class="material-icons" *ngIf="show">filter_drama</i>First</div>
<强> JS 强>
<div class="collapsible-header" id="clickedId"><i class="material-icons" id="someId">filter_drama</i>First</div>
+ jQuery lib - 以及它引发的可能出现的性能问题
您想要的只能使用CSS实现:
HTML:
$( "#clickedId" ).click(function() {
$("#someId").toggleClass('someIconClass');
});
的CSS:
<div class="collapsible-header"><i class="material-icons more">expand_more</i><i class="material-icons less">expand_less</i>First Section</div>
更新了plunker here
归功于this answer
答案 1 :(得分:0)
我建议您根据要添加的图标切换课程更改,或删除someIcon
标记上的i
课程。
在jQuery中它是
$(el).toggleClass('someIconClass')
我个人对Angular 4中的elementRef
等运气不太好,并且已经在我的应用程序中使用了jQuery。只是一个建议(不是最佳实践,我相信有人会争辩)
答案 2 :(得分:0)
我偷看了Angular materialize的代码,看起来它是一种有角度的“垫片”,它使用jQuery和其他一些解决方法来使这个CSS / JS框架在Angular 2中正常工作。这就像你想要的那样如果它是纯粹的Angular 2,会有点棘手。
'Angular方式',是让每个菜单项都有一个单独的组件来跟踪它自己的状态。它会跟踪它是展开还是折叠,甚至可以输出基于该状态的事件,这会使图标变得微不足道。它甚至可以跟踪点击的次数,并随着点击次数的增加而慢慢改变颜色。当一切都封装在自己的组件中时,这样的东西真的很容易。
除此之外,你必须手动管理菜单状态,使用类似布尔数组的东西。这样做的问题在于,您将在不同的地方为同一事物管理2个单独的视图状态 - 并且它们可能并不总是同步。一个在你的图标的组件中,一个在...实现代码的任何地方来自...实现代码可能使用CSS:主动选择器来更改点击的东西,你可以使用(点击)处理程序在Angular中,可以在点击时更改某些内容,但由于多种原因,这些内容并不总是保证同步。因此,如果他们不同步,图标将会倒退,并且很难修复。
事实上,这可能是 更容易在Angular中使用jQuery的情况,简单地说,您正在使用的技术也使用jQuery。
但是,如果你真的想让它在Angular中使用这个框架,那么你可以做到这一点,只需要预先知道它会非常脆弱。
我会在组件中创建一个表示菜单的对象数组。每个对象都可以保存其菜单文本,扩展文本和表示其展开/折叠状态的布尔值。
您可以在组件外部定义一个接口,以便根据需要对其进行类型检查。
import { Component } from '@angular/core'
export interface CollapsibleItem {
label: string;
text: string;
state: boolean;
}
@Component({
selector:'whateveryouwant',
template: `
<ul class="collapsible" data-collapsible="accordion">
<li *ngFor="let item of menuItems; let i = index" (click)="menuClick(i)">
<div class="collapsible-header">
<i class="material-icons" *ngIf="item.state"> minus-icon </i>
<i class="material-icons" *ngIf="!item.state"> plus-icon </i>
{{ item.label }}
</div>
<div class="collapsible-body">
<span> {{ item.text }} </span>
</div>
</li>
`,
styles: ['']
})
export class YourComponentName {
constructor() { }
menuItems: CollapsibleItem[] = [
{ label: 'First', text: 'Lorem Ipsum', state: false },
{ label: 'Second', text: 'Lorem Ipsum', state: false },
{ label: 'Third', text: 'Lorem Ipsum', state: false },
];
menuClick(clickedItem: number) {
this.menuItems[clickedItem].state = !this.menuItems[clickedItem].state // flips the boolean value for the clicked item
for (let item of this.menuItems) {
if ( item !== this.menuItems[clickedItem] ) {
item.state = false;
}
}
// the for loop goes through the array and sets each item to false *if* its not the item that was clicked
}
}
看看......当你在Angular中使用它时,你可能刚刚构建了自己的菜单项组件,这些组件更易于使用且更具可扩展性:)你正在创建一个对象数组每个对象有几个不同的属性,并尝试通过每次单击来管理它们。这就是创建组件的原因!你可以为每个项目创建一个简单的包装器组件,但是我不确定它是如何工作的,因为实体化的东西是使用jQuery和CSS来选择东西。使用普通组件视图封装可能无法预测。
使用ngIf切换图标的替代方法是绑定到innerText属性,并根据状态切换文本。
<i class="material-icons" [innerText]="item.state ? 'plus-icon' : 'minus-icon'"></i>
但是我不确定物化框架是否会快速或完全接受对innerText的更改。如果你想尝试混合这样的技术,最好同时渲染和切换它们。
此外,我不知道'plus-icon'或'minus-icon'是如何引用这些图标的,但你可能会明白这一点:p