angular 中可点击的 table 个单元格

Clickable table cells in angular

我有一个 table 有行。当我点击一个单元格时,它的颜色变成了红色,但一次只能有一个是红色的。如果我点击另一个单元格,之前的单元格应该不再是红色的。我不知道如何一次只使一个单元格变红。你有什么想法吗?

html 文件:

<table>
  <tr appFocusCell><td > </td></tr>
  <tr appFocusCell><td> </td></tr>
  <tr appFocusCell><td> </td></tr>
  <tr appFocusCell><td> </td></tr>
  <tr appFocusCell><td> </td></tr>
  <tr appFocusCell><td> </td></tr>
  <tr appFocusCell><td></td></tr>
</table>

焦点-cell.directive 文件:

import {Directive, ElementRef, HostListener, Renderer2} from '@angular/core';

@Directive({
  selector: '[appFocusCell]'
})
export class FocusCellDirective {

  constructor(private e:ElementRef,private render: Renderer2) { }
     ngOnInit() {

      }

      @HostListener('click')
  onClick(){
    const div = this.e.nativeElement;
    this.render.setStyle(div,'background','red')
      }

}

您可能想要添加关于当前选择哪一行的逻辑,方法是创建一个父指令来为当前单击的行添加书签。

这个想法是,有了关于当前点击哪一行的信息,这个父指令可以删除点击的旧行的突出显示,并改为突出显示新点击的行。

这是一个示例解决方案。我还没有测试过它,但希望它背后的想法很清楚。

<table appTable> <!--  make new directive-->
  <tr appFocusCell>...</tr>
  <tr appFocusCell>...</tr>
  ...
</table>
@Directive({
  selector: '[appFocusCell]'
})
export class FocusCellDirective implements OnDestroy {
  readonly onClick$ = new Subject<void>(); //  emit when host is clicked

  @HostListener('click')
  onClick() {
    this.onClick$.next();
  }

  //  set/unset row background color whether active/inactive
  set isActive(isActive: boolean) {
    this.e.style.backgroundColor = isActive ? 'red' : 'unset';
  }

  constructor(private e: ElementRef<HTMLElement>) { }

  ngOnDestroy() {
    this.onClick$.complete();
  }
}
@Directive({
  selector: '[appTable]'
})
export class AppTableDirective implements AfterContentInit, OnDestroy {
  private clickedRow: FocusCellDirective | null = null; //  bookmark currently clicked row

  @ContentChildren(FocusCellDirective, { descendants: true })
  private rows!: QueryList<FocusCellDirective>; //  get all table rows

  private onDestroy = new Subject<void>();

  ngAfterContentInit() {
    //  listen to any rows clicked
    this.rows.forEach((row) => {
      row.onClick$
        .pipe(takeUntil(this.onDestroy))
        .subscribe(() => this.setClicked(row)); //  update currently clicked row
    });
  }

  private setClicked(row: FocusCellDirective) {
    if(this.clickedRow !== null) {
      this.clickedRow.isActive = false; //  remove highlight of previously clicked row
    }

    row.isActive = true; //  highlight currently clicked row

    this.clickedRow = row; //  bookmark currently clicked row
  }

  ngOnDestroy() {
    this.onDestroy.next();
    this.onDestroy.complete();
  }
}

以下是代码示例

html

<table border="1">
  <tbody>
    <tr>
      <td appCellClick>
        Cell1.1
      </td>
      <td appCellClick>
        Cell1.2
      </td>
    </tr>
    <tr>
      <td appCellClick>
        Cell2.1
      </td>
      <td appCellClick>
        Cell2.2
      </td>
    </tr>
  </tbody>
</table>

指令

import { Directive, HostListener, Renderer2 } from '@angular/core';

@Directive({
  selector: '[appCellClick]',
})
export class CellClickDirective {
  
  @HostListener('click', ['$event']) onClick(ev) {
    
    const curEl = ev.target; //TAKE CLICKED CELL ELEMENT
    
    let parentEl:any = {};

    // CHECK THE PARENT TABLE ELEMENT
    const parentChecker = (el) => {
      if (el.nodeName == 'TABLE') {
        parentEl = el;
      } else {
        parentChecker(el.parentElement);
      }
    };
    
    parentChecker(curEl);
    // PARENT TABLE FOUND - REMOVE EXISTING CSS-CLASS
    if(parentEl){
      const addedBg = parentEl.querySelectorAll('td.bg-red');
      addedBg.forEach((e) => {
        e.setAttribute('class', e.getAttribute('class').replace('bg-red',''));
      });
    }    

    this.renderer.addClass(curEl, 'bg-red');

  }

  constructor(
    private renderer: Renderer2
  ) {}
}

css

.bg-red{
  background-color: red;
}