功能目標:
用於獲取用戶輸入表格行、列數的組件,隨鼠標移動,表格行列數變化,覆蓋區域填充藍色,效果如下圖所示。
思路:
通過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>