在此处使用Angular 6
我想要一些有关设计UI组件的信息。因此,基本上我们已经在AngularJs中设计了当前的功能 我想知道是否有更好的方法使用Angular 6的新应用程序。
下面是我要设计的UI流程。
用户基本上在顶部填写了一些文本框和下拉菜单。
完成上述选择后,我将显示一个HTML表,其中包含3个静态列和几个ex按钮,如下所示:
ID类型Env +添加列 -删除行 +添加行
在Id,Type和Env之上是3个静态列,它们始终存在。现在,如果用户想添加更多列(动态),则可以单击“添加列”按钮,用户可以在其中输入自己的特定名称。从功能上讲,还应该删除动态列。 一旦用户完成添加列,他可以单击“添加行”,这将创建一个动态行,然后用户可以将数据输入到表中。 用户添加行后,可以单击“删除行”按钮删除该行。
在用户完成向表中添加列和行后,在末尾有一个提交按钮,该按钮会将上述Json格式的内容发送到我的API 然后保存整个表格。
仅供参考,我已经在angularjs中有了一个有效的版本,在其中我对每一行使用contenteditable,如下所示:
<tr ng-repeat="r in targetTable.rows">
<td class="unique-id">{{r.id}}</td>
<td contenteditable="true" ng-repeat="column in targetTable.columns" ng-model="r[column.id]" ng-blur="!r.id? addNewRow(r[column.id], r): undefined"></td>
<td class="blank" colspan="2"></td>
</tr>
在此处查看演示
https://codepen.io/anon/pen/QXwjwM
我需要输入的内容是如何设计html表,使其具有在Angular 6中添加/删除动态行和列的所有功能。是否有开放源代码可供使用,或者有人可以帮助我举例说明。或者,如果我需要手动创建所有这些。就像我在AngularJs中所做的一样。
谢谢
有人输入吗?
答案 0 :(得分:2)
结合我的两个评论,我创建了这个stackblitz
我使用了材料表,因为我懒于格式化表。如前所述,我们唯一需要使用mat-table的东西就是将Data Array控件作为数据源放置
dataSource = this.myformArray.controls;
表的列变得像
<ng-container matColumnDef="surname">
<th mat-header-cell *matHeaderCellDef> Surname </th>
<td mat-cell *matCellDef="let element">
<input arrow-div [formControl]="element.get('surname')">
</td>
</ng-container>
是的,只需使用[formControl] = element.get('nameOfField')
有趣的工作是使按键能够在“单元”之间移动。
我使用指令。但是由于我讨厌用@Output()
创建指令,因此我使用了辅助服务。
如果我们不使用服务,则我们的.html如下
<input arrow-div [formControl]="element.get('id')" (arrowEvent)="move($event)">
<input arrow-div [formControl]="element.get('name')" (arrowEvent)="move($event)">
<input arrow-div [formControl]="element.get('surname')" (arrowEvent)="move($event)">
...
如果我们使用服务,我们的html将会变得更加透明
<input arrow-div [formControl]="element.get('id')" >
<input arrow-div [formControl]="element.get('name')" >
<input arrow-div [formControl]="element.get('surname')" >
...
在应用程序中,我们订阅了该服务。
服务很简单
export class KeyBoardService {
keyBoard:Subject<any>=new Subject<any>();
sendMessage(message:any)
{
this.keyBoard.next(message)
}
}
只是一个主题和一种将值发送给主题的方法。
该指令仅在箭头键按下时侦听并发送密钥发送者。好吧,我发送了一个{element:...,acction:..}类型的对象来发送更多信息。
export class ArrowDivDirective {
constructor( private keyboardService:KeyBoardService,public element:ElementRef){}
//@Output() arrowEvent:EventEmitter<any>=new EventEmitter();
@HostListener('keydown', ['$event']) onKeyUp(e) {
switch (e.keyCode)
{
case 38:
this.keyboardService.sendMessage({element:this.element,action:'UP'})
break;
case 37:
if (this.element.nativeElement.selectionStart<=0)
{
this.keyboardService.sendMessage({element:this.element,action:'LEFT'})
e.preventDefault();
}
break;
case 40:
this.keyboardService.sendMessage({element:this.element,action:'DOWN'})
break;
case 39:
if (this.element.nativeElement.selectionStart>=this.element.nativeElement.value.length)
{
this.keyboardService.sendMessage({element:this.element,action:'RIGTH'})
e.preventDefault();
}
break;
}
}
}
好吧,当您单击输入和右箭头时,我会考虑您是第一次输入还是在输入初始时发送或不发送密钥。
app.component只需要订阅服务并使用ViewChildren存储所有输入。小心点!观看者在垫子桌子中的顺序从上到下,从左到右依次为
@ViewChildren(ArrowDivDirective) inputs:QueryList<ArrowDivDirective>
constructor(private keyboardService:KeyBoardService){}
ngOnInit()
{
this.keyboardService.keyBoard.subscribe(res=>{
this.move(res)
})
}
move(object)
{
const inputToArray=this.inputs.toArray()
const rows=this.dataSource.length
const cols=this.displayedColumns.length
let index=inputToArray.findIndex(x=>x.element===object.element)
switch (object.action)
{
case "UP":
index--;
break;
case "DOWN":
index++;
break;
case "LEFT":
if (index-rows>=0)
index-=rows;
else
{
let rowActual=index%rows;
if (rowActual>0)
index=(rowActual-1)+(cols-1)*rows;
}
break;
case "RIGTH":
console.log(index+rows,inputToArray.length)
if (index+rows<inputToArray.length)
index+=rows;
else
{
let rowActual=index%rows;
if (rowActual<rows-1)
index=(rowActual+1);
}
break;
}
if (index>=0 && index<this.inputs.length)
{
inputToArray[index].element.nativeElement.focus();
}
}
* UPDATE 如果要添加动态列,请添加新的两个变量(加上“ displayedColumns”
displayedColumns: string[] = ['name','surname','delete'];
displayedHead:string[]=['Name','Surname']
displayedFields:string[] = ['name','surname'];
我们的桌子变成
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<!-- All columns -->
<ng-container *ngFor="let col of displayedFields;let i=index" [matColumnDef]="col">
<th mat-header-cell *matHeaderCellDef> {{displayedHead[i]}} </th>
<td mat-cell *matCellDef="let element">
<input arrow-div [formControl]="element.get(col)">
</td>
</ng-container>
<!---column delete-->
<ng-container matColumnDef="delete">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let element;let i=index;">
<button arrow-div mat-button (click)="delete(i)">delete</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
添加列的新函数必须向数组的每个FormGroup添加一个FormControl,实现变量displayColumns,displayedHead和displayFields
addColumn()
{
let newField="Column"+(this.displayedFields.length+1)
this.myformArray.controls.forEach((group:FormGroup)=>{
group.addControl(newField,new FormControl())
})
this.displayedHead.push(newField)
this.dataSource = [...this.myformArray.controls];
this.displayedFields.push(newField);
this.displayedColumns=[...this.displayedFields,"delete"];
}
在此another stackblitz中,我添加了此功能(以及如何删除行和如何创建新行)
答案 1 :(得分:0)