Skip to content
Snippets Groups Projects
Commit 0c208e85 authored by Sophie Richard's avatar Sophie Richard Committed by Patriarche Rémi
Browse files

fix(select): issue performance select firefox, update template

parent 2744d24c
No related branches found
No related tags found
No related merge requests found
......@@ -24,6 +24,7 @@
- fix(input): erreur js si usage dans une modale
- fix(tile): dépréciation de `detail` en faveur de `detailBottom` pour homogénéiser avec la carte
- fix(select): suppression de la conversion automatique des values en string (ex. une value passée en number reste dorénavant un number)
- fix(select): problème de performance lors de l'affichage d'un grand nombre d'options sur Firefox
- doc(card/tile): correction documentation detail carte et tuile de téléchargement
- doc(display): fix les modales non visibles dans la doc de Storybook
......
<form *ngIf="!showNg" [formGroup]="formGroup">
<dsfr-form-select id="1" [label]="'Reactive form'" [options]="options" formControlName="simple"></dsfr-form-select>
<p>Sélection : {{ formGroup.controls.simple.value }}</p>
<dsfr-form-select
id="2"
[compareWith]="compareFn"
[label]="'Reactive form avec objets (utilisation de compareWith)'"
[options]="optionsObjects"
formControlName="withObjects"></dsfr-form-select>
<p>Sélection : {{ formGroup.controls.withObjects.value?.id }}</p>
</form>
<p>Sélection : {{ formGroup.controls.withObjects.value?.id }}</p>
......@@ -30,6 +30,8 @@ export class DemoFormSelectComponent implements OnInit {
{ label: 'Option 4', value: { id: '4', label: 'test' } },
];
listOptions: any[] = [];
constructor(private readonly fb: FormBuilder) {}
ngOnInit(): void {
......@@ -38,8 +40,11 @@ export class DemoFormSelectComponent implements OnInit {
withObjects: [],
});
for (let i = 0; i < 500; i++) {
this.optionsObjects.push({ label: 'Option ' + i, value: { id: i, label: 'test' } });
}
this.formGroup.controls.simple.setValue('2');
this.formGroup.controls.withObjects.setValue({ id: '2' });
this.formGroup.controls.withObjects.setValue({ id: 2 });
}
compareFn(c1: any, c2: any): boolean {
......
......@@ -10,7 +10,10 @@
<ng-content *ngIf="!label" select="[label]"></ng-content>
<span *ngIf="hint" class="fr-hint-text">{{ hint }}</span>
</label>
<!-- Select sans groupes. Duplication du select pour pb perf. affichage d'options sur firefox si utilisation d'un ng-container -->
<select
*ngIf="noGroup"
class="fr-select"
[ngClass]="{ 'fr-select--error': error, 'fr-select--valid': valid }"
[id]="inputId"
......@@ -23,12 +26,40 @@
[compareWith]="compareFn"
(change)="onChange()">
<option *ngIf="!value" [value]="value" selected hidden disabled>{{ placeholder }}</option>
<ng-container *ngFor="let option of options">
<option
*ngFor="let option of options; trackBy: trackByIndex"
[ngValue]="option.value"
[disabled]="option.disabled || null">
{{ option.label }}
</option>
</select>
<!-- Select avec groupes. Ne sera pas optimisé pour FF, voir pour un fix avec angular 17 -->
<select
*ngIf="!noGroup"
class="fr-select"
[ngClass]="{ 'fr-select--error': error, 'fr-select--valid': valid }"
[id]="inputId"
[attr.name]="name || null"
[(ngModel)]="value"
[attr.aria-describedby]="messagesGroupId"
[attr.aria-label]="ariaLabel"
[disabled]="disabled"
[attr.required]="required || null"
[compareWith]="compareFn"
(change)="onChange()">
<option *ngIf="!value" [value]="value" selected hidden disabled>{{ placeholder }}</option>
<ng-container *ngFor="let option of options; trackBy: trackByIndex">
<option *ngIf="!option.options" [ngValue]="option.value" [disabled]="option.disabled || null">
{{ option.label }}
</option>
</ng-container>
<ng-container *ngFor="let option of options; trackBy: trackByIndex">
<optgroup *ngIf="option.options" [label]="option.label">
<option *ngFor="let option of option.options" [ngValue]="option.value" [disabled]="option.disabled || null">
<option
*ngFor="let option of option.options; trackBy: trackByIndex"
[ngValue]="option.value"
[disabled]="option.disabled || null">
{{ option.label }}
</option>
</optgroup>
......
......@@ -63,6 +63,15 @@ export class DsfrFormSelectComponent extends DefaultControlComponent<any> implem
@Output() selectChange = new EventEmitter<any>();
/** @internal */ messagesGroupId: string;
/**
* @internal
* https://github.com/angular/angular/issues/50233 : issue performance with ng-container/ng-template inside select for Firefox
* Dans le cas ou il n'y a pas de groupe, supprimer le ng-container avec ngFor côté template
* fixme: vérifier/améliorer le fix lors du passage à angular 17.
*/
noGroup: boolean = false;
/** @internal fonction de comparaison */
compareFn: (o1: any, o2: any) => boolean = Object.is;
......@@ -98,6 +107,9 @@ export class DsfrFormSelectComponent extends DefaultControlComponent<any> implem
/** @internal */
ngOnInit() {
if (!this.options.find((o) => o.options)) {
this.noGroup = true;
}
super.ngOnInit();
this.messagesGroupId = `${this.inputId}-messages`;
this.placeholder ??= this.i18n.t('select.placeholder');
......@@ -118,6 +130,10 @@ export class DsfrFormSelectComponent extends DefaultControlComponent<any> implem
this.selectChange.emit(this.value);
}
trackByIndex = (index: number): number => {
return index;
};
private findOption(value: any, options: DsfrSelectOption[]): any {
return options?.find(
(option) =>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment