功能目标:
用于获取用户输入表格行、列数的组件,随鼠标移动,表格行列数变化,覆盖区域填充蓝色,效果如下图所示。
思路:
通过ngFor动态构造表格的行和列,通过maxrow,maxcol 控制表格白色区域,用rows,cols控制表格蓝色区域,使maxrow大于rows、maxcol大于cols。
由于ngFor没有i<n迭代功能,使用[0,1,2....]数组来实现。
代码:
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-tablecreator',
template: `
<table border="1" cellpadding="8" style="border-collapse:collapse;" (mouseover)="mouseover($event)" (click)="cellclick.emit($event)">
<tbody>
<tr *ngFor="let i of numbers.slice(0,maxrow)">
<td *ngFor="let j of numbers.slice(0,maxcol)" [style.background-color]="(i<rows&&j<cols)?'blue':'white'"></td>
</tr>
</tbody>
</table>
<div>{{rows}}×{{cols}}</div>
`
})
export class TableCreatorComponent {
@Input() rows: number;
@Input() cols: number;
@Output() cellclick = new EventEmitter<Event>();
numbers: number[];
get maxrow() {
return this.rows < 4 ? 5 : this.rows + 1;
}
get maxcol() {
return this.cols < 4 ? 5 : this.cols + 1;
}
constructor() {
this.rows = 1;
this.cols = 1;
this.numbers = Array(100).fill(0).map((x, i) => i);
}
mouseover(e) {
let node = (e.srcElement != null) ? e.srcElement : e.target;
const td = this.getParentByName(node, 'TD');
if (td != null) {
const row2 = this.getParentByName(td, 'TR');
this.rows = row2.sectionRowIndex + 1;
this.cols = td.cellIndex + 1;
this.consume(e);
}
}
/**
* Returns the first ancestor of the current selection with the given name.
*/
getParentByName(node, name, stopAt?) {
while (node != null) {
if (node.nodeName == name) {
return node;
}
if (node == stopAt) {
return null;
}
node = node.parentNode;
}
return node;
}
consume(evt: Event): void {
if (evt.preventDefault) {
evt.stopPropagation();
evt.preventDefault();
}
// Opera
evt.isConsumed = true;
// Other browsers
if (!evt.preventDefault) {
evt.returnValue = false;
}
}
}
使用:
截图中使用了按钮和primeng OverlayPanel,tablecreator置于OverlayPanel中,在点击按钮时toggle OverlayPanel,在表格cellclick时再次toggle OverlayPanel。
注意cellclick toggle 时需要给出与第一次toggle等价的target,否则OverlayPanel会再次出现在别的位置。
<button pButton type="button" icon="fa fa-table" [title]="'table'|lang" (click)="op.toggle($event)"></button>
<p-overlayPanel #op>
<app-tablecreator (cellclick)="op.toggle(null,op.target)"></app-tablecreator>
</p-overlayPanel>