Работаю над приложением для составления отчетов о расписании для ресурсов сайта. Для разных местоположений может быть более 500-600 позиций, каждая строка имеет не менее 16 полей формы, хотя только 8 имеют «назначенный» компонент HTML.
общий вид формы выглядит следующим образом: Каждая позиция – это отдельный компонент формы в
FormArray
, который является частью родительской формы. Сама форма «управляется» службой форм, которая обрабатывает большую часть извлечения данных, а также добавления и удаления элементов строки.
Генерация FormArry выполняется в formService
//Initiate listener on service
this.service.getDate.subscribe((data: IInterface[]) => {
data.map(lineitem => {
const array = this.getFormArray(lineitem.group);
lineitem.id = array.length + 1;
let iform = this.fb.group(new LineItemForm(lineitem));
array.push(iform);
});
});
Ini для данных запускается одним вызовом из родительской формы по нажатию кнопки, вышеприведенный слушатель распределяет данные по 4 отдельным массивам с помощью lineitem.group
. Что все работает как положено.
В родительской форме HTML формы элементов строки генерируются следующим образом, а Array
происходит из formService
, где он фильтруется по номеру страницы в статический массив (т. е. службе не нужно вызывать или фильтровать при извлечении массива в родительском поскольку это уже было сделано при извлечении данных, поэтому Array
должен быть «готов к работе»)
<lineitem *ngFor="let lineitem of Array?.controls; let i = index"
[index]="i"
[LineItemForm]="lineitem"
(deleteLineItem)="deleteLineItem($event)">
</lineitem>
компонент lineitem-form имеет следующие спецификации и свойства.
После рендеринга представления строки каждая форма строки отделяется от процесса ChangeDetection, и все подписки помещаются в массив, чтобы мы могли отписаться от всех после ngOnDestroy. На данный момент инициировано только 3 слушателя подписки. (1 для типа сотрудника, один для массива сотрудников (который поступает из службы и один для массива ресурсов (также из службы))
@Component({
selector: 'lineitem',
templateUrl: './lineitem.component.html',
styleUrls: ['./lineitem.component.css', './../form.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})
constructor(
private formService: formService,
private modalService: BsModalService,
private cd: ChangeDetectorRef
) {
}
ngAfterViewInit() {
this.cd.detach();
}
ngOnDestroy() {
this.subscriptions.forEach(c => c.unsubscribe());
}
Поля с понедельника по воскресенье имеют (change)
привязку к методу расчета в компоненте формы, в конце метода ChangeDetectionRef
запускается для запуска this.cd.detectChanges()
для обновления каждой отдельной строки-формы.
calculateThings(){
// … do some calculations and form-field sets
//Trigger change detection cycle
this.cd.detectChanges();
}
Родительская форма установлена на ChangeDetection.Default
(хотя переключение на OnPush
не уменьшает количество слушателей)
Чтобы решить (частично) проблему, я разделил общее количество элементов строки на вкладках, каждая вкладка генерируется только при фактическом отображении с использованием привязки *ngIf
. Это уменьшает количество слушателей примерно до 2000-4000 на активной вкладке. Однако, если пользователь щелкает туда-сюда между двумя вкладками, слушатели снова быстро начинают складываться.
На каком-то этапе — хотя и нерегулярно и без ясной «причины» — количество слушателей снова сбрасывается до более управляемых 2000-3000 (все еще много, но это работает). Я могу отобразить около 35-50 строк (т. заметна задержка во времени отклика.
Это приводит к нескольким вопросам:
- Есть ли способ «очистить» слушателей при переходе с вкладки на вкладку (т.е. при повторном создании DOM)
- Есть ли способ «сбросить» DOM, чтобы количество слушателей упало почти до нуля
- Каков наилучший (или рекомендуемый) способ обработки этого количества строк/поля формы (если я посмотрю, например, на ag-Grid, они, похоже, смогут генерировать 10000 строк при 100 столбцах, не превышая 2000 слушателей?? ?, правда, без вычисления полей, насколько я вижу)
- Единственный способ контролировать количество слушателей, ограничивая фактическое количество полей формы в активном DOM?
Я был бы признателен за любые подсказки и советы, которые могли бы предоставить некоторую дополнительную информацию.
В текущем решении я разделяю массив форм на вкладки и разбиваю на страницы массивы на каждой вкладке, содержащие более 50 строк. Это работает, но мне любопытно, есть ли «более чистые» решения?
PS: Я был бы признателен, если бы мы могли избежать комментариев, например, зачем вам вообще нужно столько полей формы. Что, хотя и является закономерным вопросом, не помогает, поскольку это критерий дизайна для развертывания его среди пользователей. Если у вас есть конструктивная информация о том, как ввести 7 дневных значений для 600 ресурсов в 1 форму, тогда я весь слушаю?
ChangeDetectionStrategy.OnPush
? - person Krishnan   schedule 06.12.2019