Skip to content

Commit

Permalink
Use new <bit-form-field> component in Excluded domains settings.
Browse files Browse the repository at this point in the history
Changing to new <bit-form-field> component necessitates modifying form to use ReactiveForms conventions. To handle this change, the deletable/uneditable domain state and new form control state are managed separately, including clearing the form state on save. Fields which compute vaules from the former state should now compute both values (see domain count); [formGroup], formArrayName, formControlName all necessary directives/properties on form and children.
  • Loading branch information
blackwood committed Jan 28, 2025
1 parent d001854 commit 76271b1
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,36 @@
<bit-section *ngIf="!isLoading">
<bit-section-header>
<h2 bitTypography="h6">{{ "domainsTitle" | i18n }}</h2>
<span bitTypography="body2" slot="end">{{ excludedDomainsState?.length || 0 }}</span>
<span bitTypography="body2" slot="end">{{
excludedDomainsState?.length + domainForms?.value?.length
}}</span>
</bit-section-header>

<ng-container *ngIf="excludedDomainsState">
<bit-item
*ngFor="let domain of excludedDomainsState; let i = index; trackBy: trackByFunction"
<bit-item
*ngFor="let domain of excludedDomainsState; let i = index; trackBy: trackByFunction"
>
<bit-item-content *ngIf="i < fieldsEditThreshold">
<div id="excludedDomain{{ i }}">{{ domain }}</div>
</bit-item-content>
<button
*ngIf="i < fieldsEditThreshold"
appA11yTitle="{{ 'remove' | i18n }}"
bitIconButton="bwi-minus-circle"
buttonType="danger"
size="small"
slot="end"
type="button"
(click)="removeDomain(i)"
></button>
</bit-item>
<form [formGroup]="domainListForm">
<bit-card
formArrayName="domains"
*ngFor="let domain of domainForms.controls; let i = index"
>
<bit-item-content>
<bit-label *ngIf="i >= fieldsEditThreshold">{{
"websiteItemLabel" | i18n: i + 1
}}</bit-label>
<bit-form-field>
<bit-label>{{ "websiteItemLabel" | i18n: i + fieldsEditThreshold + 1 }}</bit-label>
<input
*ngIf="i >= fieldsEditThreshold"
bitInput
#uriInput
appInputVerbatim
bitInput
Expand All @@ -35,25 +52,14 @@ <h2 bitTypography="h6">{{ "domainsTitle" | i18n }}</h2>
name="excludedDomain{{ i }}"
type="text"
(change)="fieldChange()"
[(ngModel)]="excludedDomainsState[i]"
formControlName="{{ i }}"
/>
<div id="excludedDomain{{ i }}" *ngIf="i < fieldsEditThreshold">{{ domain }}</div>
</bit-item-content>
<button
*ngIf="i < fieldsEditThreshold"
appA11yTitle="{{ 'remove' | i18n }}"
bitIconButton="bwi-minus-circle"
buttonType="danger"
size="small"
slot="end"
type="button"
(click)="removeDomain(i)"
></button>
</bit-item>
</ng-container>
<button bitLink class="tw-pt-2" type="button" linkType="primary" (click)="addNewDomain()">
<i class="bwi bwi-plus-circle bwi-fw" aria-hidden="true"></i> {{ "addDomain" | i18n }}
</button>
</bit-form-field>
</bit-card>
<button bitLink class="tw-pt-2" type="button" linkType="primary" (click)="addNewDomain()">
<i class="bwi bwi-plus-circle bwi-fw" aria-hidden="true"></i> {{ "addDomain" | i18n }}
</button>
</form>
</bit-section>
</div>
<popup-footer slot="footer">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ import {
ElementRef,
OnDestroy,
AfterViewInit,
ViewChildren,
ViewChildren, OnInit,
} from "@angular/core";
import { FormsModule } from "@angular/forms";
import {
FormsModule,
ReactiveFormsModule,
FormBuilder,
FormGroup,
FormArray,
} from "@angular/forms";
import { RouterModule } from "@angular/router";
import { Subject, takeUntil } from "rxjs";

Expand Down Expand Up @@ -45,6 +51,7 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co
CommonModule,
FormFieldModule,
FormsModule,
ReactiveFormsModule,
IconButtonModule,
ItemModule,
JslibModule,
Expand All @@ -59,7 +66,7 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co
TypographyModule,
],
})
export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy {
export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy, OnInit {
@ViewChildren("uriInput") uriInputElements: QueryList<ElementRef<HTMLInputElement>> =
new QueryList();

Expand All @@ -68,6 +75,7 @@ export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy {
isLoading = false;
excludedDomainsState: string[] = [];
storedExcludedDomains: string[] = [];
domainListForm: FormGroup;
// How many fields should be non-editable before editable fields
fieldsEditThreshold: number = 0;

Expand All @@ -77,10 +85,21 @@ export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy {
private domainSettingsService: DomainSettingsService,
private i18nService: I18nService,
private toastService: ToastService,
private formBuilder: FormBuilder,
) {
this.accountSwitcherEnabled = enableAccountSwitching();
}

ngOnInit() {
this.domainListForm = this.formBuilder.group({
domains: this.formBuilder.array([]),
});
}

get domainForms() {
return this.domainListForm.get("domains") as FormArray;
}

async ngAfterViewInit() {
this.domainSettingsService.neverDomains$
.pipe(takeUntil(this.destroy$))
Expand Down Expand Up @@ -117,8 +136,7 @@ export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy {
}

async addNewDomain() {
// add empty field to the Domains list interface
this.excludedDomainsState.push("");
this.domainForms.push(this.formBuilder.control(null));

await this.fieldChange();
}
Expand Down Expand Up @@ -148,7 +166,11 @@ export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy {
this.isLoading = true;

const newExcludedDomainsSaveState: NeverDomains = {};
const uniqueExcludedDomains = new Set(this.excludedDomainsState);

const uniqueExcludedDomains = new Set([
...this.excludedDomainsState,
...this.domainForms.value,
]);

for (const uri of uniqueExcludedDomains) {
if (uri && uri !== "") {
Expand Down Expand Up @@ -194,13 +216,14 @@ export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy {
title: "",
variant: "success",
});

this.domainForms.clear();
} catch {
this.toastService.showToast({
message: this.i18nService.t("unexpectedError"),
title: "",
variant: "error",
});

// Don't reset via `handleStateUpdate` to preserve input values
this.isLoading = false;
}
Expand Down

0 comments on commit 76271b1

Please sign in to comment.