Почему неудачно выбрана модель выбора Angular Mat Table 2? - PullRequest
0 голосов
/ 01 июня 2018

Это достаточно простой вопрос (TLDR;):

Почему неудачно выбрана модель выбора Angular Mat Table 2?

В частности, почему она терпит неудачу при передаче точной копии объектак select() или toggle() методам.

Но я включаю в свой процесс отладки большую часть, отсюда и длину:

, не пугайтесь этого, хотя это то, что любой может прочитатьчерез полторы минуты.

Контекст:

  • стол, изготовленный из матовый стол 2
  • , начал использовать модель выбора материала 2 selection для выбора элементов таблицы при щелчке
  • добавлен Ctrl-клик (добавьте удалить в выделение, когда вы Ctrl - клик)
  • также попытались добавить поддержку Shift-Click ( Shift - клик добавит / удалит все элементы между кликом и последним добавленным / удаленным элементом)

Что не получается:

элементы, добавленные Shift - метод выбора для выбора находится в массиве выбора, но не отображается как выбранныйd визуально, независимо от следующих щелчков / выборов (что приведет к тем же результатам, например: сохранение текущих визуальных ошибок в выборе при сохранении массива безошибочного выбора.Да, можно было бы подумать, что щелчок типа «без ошибок» впоследствии, по крайней мере, исправит неисправные, если весь массив указан в 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>
  ...

(ложь для, произошел щелчок от элемента флажка в начале строки или от простого нажатия наостальная часть строки?)

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 равен , я добавляю к выделению (это работает) и, наконец, я нахожусь в случае, когда ни одна из клавиш не удерживается, я просто отменяю выбор и устанавливаю новый элемент как единственный выбранный элемент.

Как вы также можете сделать вывод из прочтения моего кода выше,то, что я пытаюсь сделать в части «сдвиг удерживается», это получить соответствующую строку для каждой строки, которая будет выделена, и передать ее функции переключения выделения.

Отладка:

Имея ранееconsole.logged строки и заметил, что строка действительно была вся текущая строка таблицы, которую я вывел, что я мог эмулировать правильные объекты, передаваемые методу «переключаться» между точками 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.Два объекта являются ИДЕНТИЧНЫМИ. Теперь я проверил вручную 15 раз, открыв все узлы.пока == не удается.

но держи эту мысль, хотя она завораживает, у меня есть кое-что еще более завораживающее для тебя.

Глубокая проблема:

давайте console.log, наш выбор (console.log(this.selection.selected);)

  1. , затем щелкните по первому элементу нашей таблицы матов
  2. Shift-клик на четвертом
  3. Ctrl кликнуть по кнопке

что бы вы ожидали?

что в итоге ни один не выбран, потому что выбор в неправильном формате?мне бы понравилось эточто выбран только первый конец, потому что массив выбора неправильный за пределами этой точки?это также имеет смысл, чтобы все 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) был последним.

как?

этот шаблон«Различение» между «ошибочным» и «правильным» там, где человеческий глаз не может, продолжается, когда вы делаете выбор в пользу сдвига и выбора Ctrl до бесконечности.Если ваш this.selection.selected имеет длину 100000 элементов, он все равно не выделит в фактическом визуальном представлении все элементы, добавленные в его массив со сдвигом, и правильно выберет все элементы, добавленные с помощью ctrl.

Shift-Clickвверх?:

давайте смешаем это, потому что так мы получаем что-то, что в конечном итоге отклоняется от проторенного пути.

давайте попробуем отменить выделение с помощью shift

Если я сделаю еще один дерьмовый щелчок, намереваясьчтобы добавить еще три элемента и еще один управляющий щелчок для элемента ниже, а затем сдвинуть назад, щелкнуть ВВЕРХ ко второму элементу: 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, кстати, это мелкий клон, но он не пропускает подчеркивания, он использует их ссылку на память):

} 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-клика, но записанный в консоль массив выбора и все другие аспекты выбора остаются безошибочными.

Какие версии Angular, Material, OS, TypeScript, браузеры?:

windows pro 10 64-битный хром

{
  "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 голосов
/ 01 июня 2018

Хорошо, я понял это, и некоторым из вас покажется, что это было неизвестно в задаче, которую я поставил, и поэтому вы не могли догадаться, потому что я не дал вам свои полные компоненты и остальнымвам это покажется очевидным, потому что вы достаточно хорошо знаете таблицу матов и по названию моей переменной вы можете сказать, что что-то не так,

У меня есть набор из четырех локальных переменных для четырех шагов обработки моегообъект между моментом, когда он прибывает из API, и когда он отображается визуально в таблице матов.

  // [ 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() методам, считался не таким, как row

теперь с this.dataSource.filteredData Я буквально перебираю тот же массив, что и моя таблица матов.

, и это не вызывает дефектов при переключении страниц и shНапример, если щелкнуть по ift.

(кроме выбора элементов со страницы 1, он больше не может выполнять итерацию, поскольку их нет в текущем списке, чего я и хотел избежать в начале, но яЯ возьму эту ошибку над этой)

Если у кого-то есть ответ, почему js не может видеть копию объекта равной себе, я бы хотел получить ответ.

Если кто-то может увидеть, как этот объект может не соответствовать критериям модели выбора матовой таблицы и как я мог бы обмануть его, я также хотел бы знать.

Я хочу отметить вас как ответ и датьнаграда 50 баллов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...