【问题标题】:Angular 8 - How to query DOM elements by their attributes?Angular 8 - 如何通过属性查询 DOM 元素?
【发布时间】:2019-09-30 15:37:26
【问题描述】:

我有一个使用 renderer2 动态生成的 HTML 5 表格:

const td = this.renderer.createElement('td');
this.renderer.setProperty(td, 'id', letter + i);
this.renderer.setAttribute(td, 'contenteditable', 'true');
this.renderer.setAttribute(td, 'r', i + '');
this.renderer.setAttribute(td, 'c', j + '');

表格结构如下

<table _ngcontent-iji-c1="" appcreatereport="">
<tr _ngcontent-iji-c1="">
<td _ngcontent-iji-c1="">1</td>
<td _ngcontent-iji-c1="" id="A1" contenteditable="true" r="1" c="1"></td>
<td _ngcontent-iji-c1="" id="B1" contenteditable="true" r="1" c="2"></td>
<td _ngcontent-iji-c1="" id="C1" contenteditable="true" r="1" c="3"></td>
<td _ngcontent-iji-c1="" id="D1" contenteditable="true" r="1" c="4"></td>
<td _ngcontent-iji-c1="" id="E1" contenteditable="true" r="1" c="5"></td>
</tr>
...

每个&lt;td&gt;都有一个“id”、一个行号“r”和一个列号“c”

我正在尝试仅使用 Angular(所以没有 jquery),并且我查看了许多现有的数据网格,但它们从未完全涵盖我计划做的事情,并且扩展它们似乎比构建我需要的东西更复杂。

我有两个问题。

  1. 我的理解是我不应该直接在 Angular 中操作 DOM,如果元素没有本地引用,我如何访问它们? (或者当我在 renderer2 中生成 &lt;td> 元素时如何添加本地引用。&lt;TD&gt; 中的文本将需要更新,例如当我从 excel 进行复制/粘贴时。
  2. 如何按属性查询元素,所以我想要 r=1 和 c=4 的元素(而不是通过 id “D1”查询)。我只发现 @ViewChild 只适用于引用。

我目前正在通过以下方式设置 TD 元素的文本:

(document.getElementById(
          'C1'
        ) as HTMLTableDataCellElement).innerHTML = '123;

我怎样才能以更“有角度”的方式做到这一点?

【问题讨论】:

    标签: angular renderer


    【解决方案1】:

    最好的方法是更改​​设计以使用带有元素数组和*ngFor 的表格。 要将其从页面中删除,您可以使用*ngIf="elements.length === 0";

    let elements = [{r:1, c: 1, value:''}, {r:1, c: 2, value:''} ... ];
    elements[1].value = '123';
    
    <td *ngFor="let el of elements" [r] = "el.r" [c]="el.c">{{el.value}}<\td>
    

    在这种情况下,您可以直接使用元素数组访问每个 td 值。

    作为替代方案 - ng-template 可用于将表格保存在 html 中,但在需要时才显示。

    【讨论】:

    • 感谢您的建议,但该更新会帮助我更新特定的单元格。想象一下,我有一个包含 200 行和 20 列的表,并且想在文件中间的某个位置粘贴一些数据。
    • 对于这样的表,您可以拥有包含 200 个条目的数组,每个条目有 20 个属性。并且只需更新特定值。那是 Angular 风格的方法。或者只是具有 200 个条目的二维数组。实际上,您拥有多少行/单元格并不重要。
    • 谢谢,我创建了一个二维数组,并为行和列使用了两个 *ngFor。然后我可以设置值,但仍然难以检测更改:“td”是可编辑的,用户可以更改输入。
    • 要检测更改添加一些 (change)="onChange(el)" 处理程序,它将元素作为输入参数传递。如果元素有值类型(不是引用类型),你可以传递行和列索引
    【解决方案2】:

    有点不清楚你想要什么。但这里是few scenarios 的一个镜头:

    1. 选择复选框过滤列表
    2. 点击一个项目会更新另一个元素的值

    首先只是一个虚拟类:

      export class RowData {
      Name:string;
      Id:number;
      Row:number;
      Column: number;
      Visible: boolean = true;
    }
    

    使用虚拟数据:

    items: RowData[] = [
             {
              Name: "One",
              Id:1,
              Row:1,
              Column:1,
              Visible:true,
            },
            {
              Name: "Two",
              Id:2,
              Row:2,
              Column:2,
              Visible:true,
            },
            {
              Name: "Another Row",
              Id:5,
              Row:3,
              Column:3,
              Visible:true,
            },
            {
              Name: "Yep",
              Id:4,
              Row:4,
              Column:4,
              Visible:true,
            },
          ]
        }
    

    对于视图,我有两种方式绑定几个事件:

    <hello name="{{ name }}"></hello>
    <p>
      Start editing to see some magic happen :)
    </p>
    <div>
      <input type="checkbox" name="Toggle Row" (click)="toggleRows()" /> Toggle Rows <br>  
    </div>
    <div *ngFor="let item of items">
      <div (click)="showMe(item)" *ngIf=item.Visible>{{item.Name}}</div>
    </div>
    
    <label *ngIf="clicked">{{clicked.Name}}</label>
    

    以下是事件及其相关属性:

    toggleRow2Col2: boolean = true;
      clicked: RowData;
    
      showMe(elem){
        this.clicked = elem;
      }
    
      toggleRows(){
        this.toggleRow2Col2 = !this.toggleRow2Col2;
    
        if (!this.toggleRow2Col2){    
        this.items.forEach(function(item){
          if (item.Row != 2 && item.Column != 2){
            item.Visible = false;
          }
        })
        }
    
        else {
          this.items.forEach(function(item)      {
              item.Visible = true;
          })
        }
      }
    

    我们的想法是,是的,我们可以过滤和更改 DOM,仅通过属性和绑定,而 不是 通过 JS / JQuery。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-12
      • 2015-12-23
      • 2011-10-04
      • 2018-12-16
      • 2013-11-03
      • 2012-07-08
      • 1970-01-01
      • 2014-08-07
      相关资源
      最近更新 更多