Вопрос или проблема
<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 и другие поля выбора). Основная проблема, которую вы испытываете, заключается в том, что изменения на одном уровне выбора сбрасывают состояния на другом. Давайте рассмотрим, как можно улучшить вашу реализацию для решения этой проблемы.
Шаги по исправлению:
-
Инициализация 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]; } }); } }
-
Состояние выбора (selection state):
При переключении междуEscalatedRoles
необходимо убедиться, что пользователь имеет доступ к последнему состоянию выбора для каждого из полейDepartment
иDivision
. -
Использование 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>
-
Проверка изменений:
Когда вы выбираете новую роль в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
, что поможет избежать ошибок, связанных с отсутствием значений, когда вы переключаетесь между ролями. Если у вас остались вопросы, не стесняйтесь их задавать!