Как сохранить выбор в вложенных компонентах многоуровенного выбора Angular

Вопрос или проблема

<div *ngFor="let field of selectFields; let i = index">
  <div class="role-list">
    <div class="role-list-box">
      <span for="select-{{ i }}">{{ i + 1 }}:</span>
      <select multiple [(ngModel)]="EsclatedRoles[i]" class="form-control"
              name="optionvalue" #optionvalue="ngModel" (change)="onSelectionChange(i)">
        <option *ngFor="let f of roles" [value]="f.entityId">
          {{ f.name }}
        </option>
      </select>
    </div>    
  </div>
  <div class="role-container">
    <div *ngFor="let selectedRole of EsclatedRoles[i]; let j = index" class="selected-role-box">
      <p-multiSelect
        [placeholder]="'Отдел'"
        [options]="allFields"
        optionLabel="name" 
        name="multi"
        optionValue="id" 
        [(ngModel)]="userRoles[i][selectedRole].Department"
      ></p-multiSelect>
      <p-multiSelect 
        [placeholder]="'Подразделение'"
        [options]="allFields"
        optionLabel="name" 
        optionValue="id" 
        name="multisec"
        [(ngModel)]="userRoles[i][selectedRole].Division"
      ></p-multiSelect>
    </div>
  </div>
</div>

//Я уже инициализировал свой массив объектов в соответствии с количеством
userRoles = new Array(this.count).fill(null).map(() => ({}));

onSelectionChange(index: number) {
  const selectedRoles = this.task.config.EsclatedRoles[index];
  let savedRole = JSON.parse(JSON.stringify(this.task.config.userRoles[index]));  // сохраняем роли для переприсвоения
  userRoles[index] = {};
  
  if (selectedRoles) {
    selectedRoles.forEach(role => {
      if (!savedRole[role]) {
        userRoles[index][role] = { Отдел: [], Подразделение: [] };
      } else {
        userRoles[index][role] = savedRole[role];
      }
    });
  }
}

У меня есть два вложенных цикла ngFor, и для каждого выбора EscalatedRoles (2D массив) (который является полем многоразового выбора) я создаю объект с выбранной ролью в качестве ключа, внутри моего объекта у меня есть два поля многоразового выбора (отдел и подразделение). Когда я выбираю какие-либо опции в любом из отделов и подразделений, и выбираю новую EscalatedRole, выбранные опции внутри обоих p-multiselect исчезают, хотя они все еще присутствуют в объекте, следовательно, двусторонняя привязка верна, в противном случае данных не было бы. Я пробовал все, от обнаружения изменений до изменения структуры данных userRoles, но я все равно получаю ту же ошибку. Помогите мне с этим, и я хочу знать, где я допускаю ошибку или есть ли у кого-то лучшее решение.

Ответ или решение

Чтобы сохранить выбранные значения в вложенных компонентах Angular с множественным выбором, необходимо учитывать суть работы с двумя уровнями выборов (EscalatedRoles и другие поля выбора). Основная проблема, которую вы испытываете, заключается в том, что изменения на одном уровне выбора сбрасывают состояния на другом. Давайте рассмотрим, как можно улучшить вашу реализацию для решения этой проблемы.

Шаги по исправлению:

  1. Инициализация userRoles:
    Убедитесь, что структура вашего userRoles соответствует выбранным ролям. Каждую роль (selectedRole) можно инициализировать в userRoles при каждом изменении на уровне EscalatedRoles.

    onSelectionChange(index: number) {
     const selectedRoles = this.EsclatedRoles[index];
     let savedRoles = JSON.parse(JSON.stringify(this.userRoles[index]));  // сохраняем роли для последующего назначения
     this.userRoles[index] = {};  // очищаем текущий индекс перед повторной инициализацией
    
     if (selectedRoles) {
       selectedRoles.forEach(role => {
         if (!savedRoles[role]) {
           this.userRoles[index][role] = { Department: [], Division: [] };
         } else {
           this.userRoles[index][role] = savedRoles[role];
         }
       });
     }
    }
  2. Состояние выбора (selection state):
    При переключении между EscalatedRoles необходимо убедиться, что пользователь имеет доступ к последнему состоянию выбора для каждого из полей Department и Division.

  3. Использование ngModel:
    Убедитесь, что каждое p-multiSelect правильно связано с ngModel. Чтобы избежать путаницы, обновите ваши категории следующим образом:

    <p-multiSelect
       [placeholder]="'Department'"
       [options]="allFields"
       optionLabel="name"
       optionValue="id"
       [(ngModel)]="userRoles[i][selectedRole].Department"
    ></p-multiSelect>
    <p-multiSelect
       [placeholder]="'Division'"
       [options]="allFields"
       optionLabel="name"
       optionValue="id"
       [(ngModel)]="userRoles[i][selectedRole].Division"
    ></p-multiSelect>
  4. Проверка изменений:
    Когда вы выбираете новую роль в EscalatedRoles, сохраняйте текущее состояние всех полей (отдел и подразделение) в структуре данных userRoles, чтобы сохранить выбранные значения.

Пример кода

Ваш окончательный код может выглядеть примерно так:

<div *ngFor="let field of selectFields; let i = index">
  <div class="role-list">
    <div class="role-list-box">
      <span for="select-{{ i }}">{{ i + 1 }}:</span>
      <select multiple [(ngModel)]="EsclatedRoles[i]" (change)="onSelectionChange(i)" class="form-control">
        <option *ngFor="let f of roles" [value]="f.entityId">
          {{ f.name }}
        </option>
      </select>
    </div>    
  </div>
  <div class="role-container">
    <div *ngFor="let selectedRole of EsclatedRoles[i]; let j = index" class="selected-role-box">
      <p-multiSelect
          [placeholder]="'Department'"
          [options]="allFields"
          optionLabel="name"
          optionValue="id"
          [(ngModel)]="userRoles[i][selectedRole]?.Department"
      ></p-multiSelect>
      <p-multiSelect
          [placeholder]="'Division'"
          [options]="allFields"
          optionLabel="name"
          optionValue="id"
          [(ngModel)]="userRoles[i][selectedRole]?.Division"
      ></p-multiSelect>
    </div>
  </div>
</div>

Заключение

Эти изменения должны помочь сохранить ваши выборы в двух уровней компонентных вложенных компонентов. Обратите внимание на использование проверки на наличие значений (?.) при связывании с ngModel, что поможет избежать ошибок, связанных с отсутствием значений, когда вы переключаетесь между ролями. Если у вас остались вопросы, не стесняйтесь их задавать!

Оцените материал
Добавить комментарий

Капча загружается...