为什么Angular Mat Table 2选择模型失败?

时间:2018-06-01 12:09:11

标签: javascript jquery angular angular-material2 multipleselection

这是一个足够简单的问题(TLDR;):

为什么Angular Mat Table 2选择模型失败?

特别是为什么它会因为传递给select()toggle()方法的对象的副本而失败。

但是我包含了很多我的调试过程,因此长度为:

不要被它吓到,尽管这是任何人都可以在一两分钟内读到的东西。

背景:

  • mat table 2
  • 制作的表格
  • 开始使用素材2的选择模型selection点击
  • 选择表格项目
  • 添加按住Ctrl键单击(在 Ctrl - 单击时添加删除到选择)
  • 也尝试添加shift-click支持( Shift - 点击会添加/删除点击和最后添加/删除项目之间的所有项目)

失败的原因:

Shift 添加的项目 - 选择的点击方法在选择数组中,但不会在视觉上显示为选中,与以下点击/选择无关(这将产生相同的结果) EG:保持当前视觉错误的选择,同时保持一个完美无缺的选择阵列。是的人会认为如果整个阵列是正确的话,之后点击“无错误”类型将至少修复错误的类型。 console.log,但没有。。

守则:

解决Shift-select:

html:

  ...
  </div>
      </mat-cell>
    </ng-container>

    <mat-header-row *matHeaderRowDef="pinnedColumnsWSelect"></mat-header-row>
    <mat-row *matRowDef="let row; columns: pinnedColumnsWSelect;"
             class="noselect"
             [ngClass]="{ 'selected': selection.isSelected(row)}"
             (click)="addToSelection(row, $event, false)"></mat-row>
  </mat-table>
  ...

(false表示,点击是否来自行首的复选框元素,还是仅点击了行的其余部分?)

ts:

  addToSelection(row, event, checkbox){
    if(event.shiftKey && this.previous !== -1 && this.previous !== row.numberOfRow) {
      if(this.previous > row.numberOfRow){
        for(let previous = this.previous - 1; previous >= row.numberOfRow; previous-- ){
          this.selection.toggle(this.originalDataSet.filter(x => x['numberOfRow'] === previous)[0] as object[]);
        }
      }else{
        for(let previous = this.previous + 1; previous <= row.numberOfRow; previous++ ){
          this.selection.toggle(this.originalDataSet.filter(x => x['numberOfRow'] === previous)[0] as object[]);
        }
      }
    } else if(event.ctrlKey || checkbox) {
      this.selection.toggle(row);
    } else {
      if(this.originalDataSet){
        if(this.selection.selected.length === 1 && this.selection.selected[0] === row) {
        this.selection.clear();
      } else {
          this.selection.clear();
          this.selection.select(row);
        }
      }
    }
    this.previous = row.numberOfRow;
  }

你可以从上面推断我首先检查 Shift 键是否被按下。 如果是,我应用我当前导致问题的选择,如果 Shift 没有被举行但是 Ctrl ,我添加选择(这是有效的),最后我是在没有按下任何键的情况下,我只是清除选择并将新项目设置为唯一选择的项目。

你也可以通过阅读上面的代码得出结论,我在&#34;转换中试图做的事情在#34; part为每个要选择的行获取相应的行,并将其传递给选择的切换函数。

调试:

之前有console.logged行,并注意到该行确实是表的整个当前行,我推断出我可以模拟传递给方法的正确对象&#34;切换&#34;在A点和B点之间。

我的素材表接受一个对象数组作为它的数据集。每个对象对应一行,每个对象的键对应于表的标题。到目前为止一切顺利。

自己从数组中拉出右行(使用我匹配numberOfRow的过滤器,我的唯一标识符恰好计算行数(0,1,2,3,等等))应该给我同样的东西。

控制台记录这两个给我相同的东西

const y = this.originalDataSet.filter(x => x['numberOfRow'] === previous)[0];
console.log('filtered item ', y, ' row ', row, ' equal ', y === row, y == row );
然而,噩梦始于两个宣称不相等的噩梦。

现在===足够公平,但对于==,为什么?

这是怎么回事,我不知道:

filtered item  {numberOfRow: 2, nCommande: "4500131111", nLigne: "00010", nEcheance: "0001", id: {…}, …}  row  {numberOfRow: 2, nCommande: "4500131111", nLigne: "00010", nEcheance: "0001", id: {…}, …}  equal  false false

image

这是我以前在javascript中从未见过的东西。这两个对象是IDENTICAL我现在通过打开所有节点手动检查了15次。但是==失败了。

但是坚持这个想法,虽然它很迷人,但我还有更令人着迷的东西。

深层种子问题:

让我们选择控制台.log(console.log(this.selection.selected);

  1. 然后点击我们mat-table的第一个项目
  2. shift-单击第四个
  3. ctrl单击fith
  4. 你会发生什么?

    没有选择,因为选择格式不正确?我喜欢那个 只选择了第一个结束,因为选择的数组在该点之后是不正确的?这也是有道理的 是否正确选择了所有5个项目?一个人可以做梦

    没有:
    image

    好的,让我们看一下日志:

    (5) [{…}, {…}, {…}, {…}, {…}]
    0 : {numberOfRow: 0, nCommande: "2284595", nLigne: "1", nEcheance: "0", id: {…}, …}
    1 : {numberOfRow: 1, nCommande: "2284595", nLigne: "2", nEcheance: "0", id: {…}, …}
    2 : {numberOfRow: 2, nCommande: "4500131111", nLigne: "00010", nEcheance: "0001", id: {…}, …}
    3 : {numberOfRow: 3, nCommande: "4500131111", nLigne: "00020", nEcheance: "0001", id: {…}, …}
    4 : {numberOfRow: 4, nCommande: "4500634818", nLigne: "00010", nEcheance: "0001", id: {…}, …}
    length : 5
    __proto__:Array(0)
    

    我很困惑。

    你使用这个数组正确地选择了数组项目0和4,但是对于介于两者之间的所有内容,不管怎样,即使4的选择(第5项)是最后一次。

    如何?

    这种&#34;区分&#34;介于&#34;错误&#34;并且&#34;纠正&#34;人眼可以在哪里继续,当您在移位选择和无限制的ctrl选择上叠加时。如果你的this.selection.selected是100000个项目,它仍然没有在实际的视觉表示中选择所有那些添加在其中的带有移位的数组,并且已经正确选择了所有用ctrl添加的项目。

    Shift-Click up? :

    让它混淆起来,因为这就是我们如何获得最终偏离常规路径的东西。

    让我们尝试使用shift

    取消选择

    如果我再做一次屎点击打算再添加三个项目,再单击一个控件点击下面的项目,然后再点击返回UP到第二个项目: image

    没有什么能与我们目前的混乱局面分开,至少在视觉上是这样:

    (9) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
    0 : {numberOfRow: 0, nCommande: "2284595", nLigne: "1", nEcheance: "0", id: {…}, …}
    1 : {numberOfRow: 1, nCommande: "2284595", nLigne: "2", nEcheance: "0", id: {…}, …}
    2 : {numberOfRow: 2, nCommande: "4500131111", nLigne: "00010", nEcheance: "0001", id: {…}, …}
    3 : {numberOfRow: 3, nCommande: "4500131111", nLigne: "00020", nEcheance: "0001", id: {…}, …}
    4 : {numberOfRow: 4, nCommande: "4500634818", nLigne: "00010", nEcheance: "0001", id: {…}, …}
    5 : {numberOfRow: 5, nCommande: "4500634818", nLigne: "00020", nEcheance: "0001", id: {…}, …}
    6 : {numberOfRow: 6, nCommande: "4500634818", nLigne: "00030", nEcheance: "0001", id: {…}, …}
    7 : {numberOfRow: 7, nCommande: "4500634818", nLigne: "00040", nEcheance: "0001", id: {…}, …}
    8 : {numberOfRow: 8, nCommande: "4500634818", nLigne: "00050", nEcheance: "0001", id: {…}, …}
    length : 9
    
    (4) [{…}, {…}, {…}, {…}]
    0 : {numberOfRow: 0, nCommande: "2284595", nLigne: "1", nEcheance: "0", id: {…}, …}
    1 : {numberOfRow: 4, nCommande: "4500634818", nLigne: "00010", nEcheance: "0001", id: {…}, …}
    2 : {numberOfRow: 8, nCommande: "4500634818", nLigne: "00050", nEcheance: "0001", id: {…}, …}
    3 : {numberOfRow: 4, nCommande: "4500634818", nLigne: "00010", nEcheance: "0001", id: {…}, …}
    length : 4
    

    这是出乎意料的。

    为什么它保留了第4项而不是像其余部分一样取消选择它并且再添加它?

    这让我觉得还有另一个阵列用于比较我不知道。

    onChange怎么样? :

    此外

    onChange结果完全符合预期:

      ngOnInit() {
        this.selection.onChange.subscribe(x=> {
          console.log(x);
        });
      }
    

    用于从第一项到第六项的再次点击并再次返回:

    {source: SelectionModel, added: Array(1), removed: Array(0)}
    {source: SelectionModel, added: Array(1), removed: Array(0)}
    {source: SelectionModel, added: Array(1), removed: Array(0)}
    {source: SelectionModel, added: Array(1), removed: Array(0)}
    {source: SelectionModel, added: Array(1), removed: Array(0)}
    {source: SelectionModel, added: Array(1), removed: Array(0)}
    {source: SelectionModel, added: Array(0), removed: Array(1)}
    {source: SelectionModel, added: Array(0), removed: Array(1)}
    {source: SelectionModel, added: Array(0), removed: Array(1)}
    {source: SelectionModel, added: Array(0), removed: Array(1)}
    {source: SelectionModel, added: Array(1), removed: Array(0)}
    

    我检查他们指出的内容是否正确(正确的项目编号正确)。

    然而视觉效果并不合适。

    碳复制真的失败了吗? :

    另一个实验:

    我在介绍中提到过该对象的副本将被拒绝: 这是真的。

    如果我对我们迄今为止的功能性ctrl代码执行此操作它将停止运行(这是导入的underscorejs库btw,它是一个浅层克隆,但它不会忽略下属,它使用它们的内存引用):

    } else if(event.ctrlKey || checkbox) {
          const bb = _.clone(row);
          this.selection.toggle(bb);
    }
    

    这种方法也是如此(这是一个深层克隆):

    } else if(event.ctrlKey || checkbox) {
          const bb = jQuery.extend(true, {}, row);
          this.selection.toggle(bb);
    }
    

    使用ctrl-click不再可视地选择行,但控制台记录的选择数组和选择的所有其他方面仍然是完美的。

    哪些版本的Angular,Material,OS,TypeScript,浏览器? :

    windows pro 10 64bit 铬

    {
      "name": "web.ui",
      "version": "0.0.0",
      "license": "MIT",
      "scripts": {
        "ng": "ng",
        "start": "ng serve --aot",
        "build": "ng b --prod",
        "test": "ng test",
        "lint": "ng lint"
      },
      "private": true,
      "dependencies": {
        "@angular/animations": "^6.0.3",
        "@angular/cdk": "^6.1.0",
        "@angular/common": "^6.0.3",
        "@angular/compiler": "^6.0.3",
        "@angular/core": "^6.0.3",
        "@angular/forms": "^6.0.3",
        "@angular/http": "^6.0.3",
        "@angular/material": "^6.1.0",
        "@angular/platform-browser": "^6.0.3",
        "@angular/platform-browser-dynamic": "^6.0.3",
        "@angular/router": "^6.0.3",
        "@types/underscore": "^1.8.7",
        "angular-font-awesome": "^3.1.2",
        "bootstrap": "^4.0.0",
        "classlist.js": "^1.1.20150312",
        "core-js": "^2.5.3",
        "file-saver": "^1.3.8",
        "font-awesome": "^4.7.0",
        "jquery": "^3.3.1",
        "lodash": "^4.17.5",
        "ng2-ion-range-slider": "^2.0.0",
        "ngx-bootstrap": "^3.0.0",
        "ngx-dropzone-wrapper": "^6.1.0",
        "rxjs": "^6.2.0",
        "rxjs-compat": "^6.0.0-rc.0",
        "typescript": "2.7.2",
        "underscore": "^1.8.3",
        "web-animations-js": "^2.3.1",
        "zone.js": "^0.8.20"
      },
      "devDependencies": {
        "@angular-devkit/build-angular": "~0.6.5",
        "@angular/cli": "^6.0.5",
        "@angular/compiler-cli": "^6.0.3",
        "@angular/language-service": "^6.0.3",
        "@types/jasmine": "^2.8.6",
        "@types/jasminewd2": "~2.0.3",
        "@types/node": "~10.1.3",
        "codelyzer": "^4.2.1",
        "postcss-modules": "^1.1.0",
        "protractor": "~5.3.0",
        "ts-node": "~6.0.5",
        "tslint": "~5.10.0"
      }
    }
    

1 个答案:

答案 0 :(得分:0)

好的,我想出来了,你们中的一些人似乎认为这是我所提出的问题中的一个未知因素,所以你无法猜到它,因为我没有给你我的全部成分和对你们其他人来说,这似乎是显而易见的,因为你们对mat表的了解非常充分,你可以从我的变量的命名中看出有些不对劲,

我有一组四个局部变量,用于处理从API到达时以及在mat-table中以可视方式显示的对象的四个步骤。

  // [ 1 ] this first gets the api object and will serve as a store
  originalDataSet:Array<object>;

  // [ 2 ] rendered after filters
  filteredDataSet:Array<object>;

  // [ 3 ] sclice step (needs to be second to last due to dual slider for size)
  dataSlice = [];

  // [ 4 ] final. what actually is queried by Mat Table
  @ViewChild(MatSort) sort: MatSort;
  dataSource: MatTableDataSource<any>;

行(对象)在1到4之间确实是相同的,但是从那以后很多都没有丢失。

这不能回答为什么javascript认为对象的两个副本不相同但它确实回答了为什么我正在提供我的toggle()方法的对象被认为与{{1}不同}

现在使用row我真的在我的mat表中迭代同一个数组。

这不会导致切换页面和按住Shift键点击等缺陷。

(除了没有从第一页中选择项目之外,它不能再迭代,因为它们不在当前列表中,这是我想要在开始时避免的但是我会接受该错误在这一个)

如果有人回答为什么js无法看到对象的副本与我自己相同,我很乐意得到答案。

如果有人能够看到这个对象如何无法满足mat table的选择模型的标准以及我如何欺骗它,我也很想知道。

我愿意将你标记为答案并给予50分赏金。