Browse Source

fix: disable Save button in rule settings dialog until form is dirty

Migrate from ngModel to FormControl so the Save button is disabled
on initialization and only enabled once the user interacts with
the slider controls.

Closes #6479
pull/6638/head
Bortlesboat 3 days ago
parent
commit
02e3e4e30f
No known key found for this signature in database GPG Key ID: A2B96F4BB60D03A1
  1. 4
      CHANGELOG.md
  2. 36
      apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.component.ts
  3. 19
      apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html

4
CHANGELOG.md

@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improved the language localization for Spanish (`es`)
- Upgraded `countries-list` from version `3.2.2` to `3.3.0`
### Fixed
- Fixed the _Save_ button state in the rule settings dialog of the _X-ray_ section
## 2.251.0 - 2026-03-24
### Added

36
apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.component.ts

@ -2,8 +2,8 @@ import { XRayRulesSettings } from '@ghostfolio/common/interfaces';
import { GfValueComponent } from '@ghostfolio/ui/value';
import { CommonModule } from '@angular/common';
import { Component, Inject } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { Component, Inject, OnInit } from '@angular/core';
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import {
MAT_DIALOG_DATA,
@ -17,21 +17,47 @@ import { RuleSettingsDialogParams } from './interfaces/interfaces';
@Component({
imports: [
CommonModule,
FormsModule,
GfValueComponent,
MatButtonModule,
MatDialogModule,
MatSliderModule
MatSliderModule,
ReactiveFormsModule
],
selector: 'gf-rule-settings-dialog',
styleUrls: ['./rule-settings-dialog.scss'],
templateUrl: './rule-settings-dialog.html'
})
export class GfRuleSettingsDialogComponent {
export class GfRuleSettingsDialogComponent implements OnInit {
public settings: XRayRulesSettings['AccountClusterRiskCurrentInvestment'];
public thresholdMaxControl: FormControl<number>;
public thresholdMinControl: FormControl<number>;
public constructor(
@Inject(MAT_DIALOG_DATA) public data: RuleSettingsDialogParams,
public dialogRef: MatDialogRef<GfRuleSettingsDialogComponent>
) {}
public get isDirty(): boolean {
return this.thresholdMinControl.dirty || this.thresholdMaxControl.dirty;
}
public ngOnInit() {
this.thresholdMinControl = new FormControl<number>(
this.data.settings.thresholdMin,
{ nonNullable: true }
);
this.thresholdMaxControl = new FormControl<number>(
this.data.settings.thresholdMax,
{ nonNullable: true }
);
}
public onSave() {
this.dialogRef.close({
...this.data.settings,
thresholdMax: this.thresholdMaxControl.value,
thresholdMin: this.thresholdMinControl.value
});
}
}

19
apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html

@ -12,14 +12,14 @@
[isPercent]="data.rule.configuration.threshold.unit === '%'"
[locale]="data.locale"
[precision]="2"
[value]="data.settings.thresholdMin"
[value]="thresholdMinControl.value"
/>
<span class="mx-1">-</span>
<gf-value
[isPercent]="data.rule.configuration.threshold.unit === '%'"
[locale]="data.locale"
[precision]="2"
[value]="data.settings.thresholdMax"
[value]="thresholdMaxControl.value"
/>
</h6>
<div class="align-items-center d-flex w-100">
@ -35,8 +35,8 @@
[min]="data.rule.configuration.threshold.min"
[step]="data.rule.configuration.threshold.step"
>
<input matSliderStartThumb [(ngModel)]="data.settings.thresholdMin" />
<input matSliderEndThumb [(ngModel)]="data.settings.thresholdMax" />
<input matSliderStartThumb [formControl]="thresholdMinControl" />
<input matSliderEndThumb [formControl]="thresholdMaxControl" />
</mat-slider>
<gf-value
[isPercent]="data.rule.configuration.threshold.unit === '%'"
@ -58,7 +58,7 @@
[isPercent]="data.rule.configuration.threshold.unit === '%'"
[locale]="data.locale"
[precision]="2"
[value]="data.settings.thresholdMin"
[value]="thresholdMinControl.value"
/>
</h6>
<div class="align-items-center d-flex w-100">
@ -75,7 +75,7 @@
[min]="data.rule.configuration.threshold.min"
[step]="data.rule.configuration.threshold.step"
>
<input matSliderThumb [(ngModel)]="data.settings.thresholdMin" />
<input matSliderThumb [formControl]="thresholdMinControl" />
</mat-slider>
<gf-value
[isPercent]="data.rule.configuration.threshold.unit === '%'"
@ -96,7 +96,7 @@
[isPercent]="data.rule.configuration.threshold.unit === '%'"
[locale]="data.locale"
[precision]="2"
[value]="data.settings.thresholdMax"
[value]="thresholdMaxControl.value"
/>
</h6>
<div class="align-items-center d-flex w-100">
@ -113,7 +113,7 @@
[min]="data.rule.configuration.threshold.min"
[step]="data.rule.configuration.threshold.step"
>
<input matSliderThumb [(ngModel)]="data.settings.thresholdMax" />
<input matSliderThumb [formControl]="thresholdMaxControl" />
</mat-slider>
<gf-value
[isPercent]="data.rule.configuration.threshold.unit === '%'"
@ -131,7 +131,8 @@
<button
color="primary"
mat-flat-button
(click)="dialogRef.close(data.settings)"
[disabled]="!isDirty"
(click)="onSave()"
>
<ng-container i18n>Save</ng-container>
</button>

Loading…
Cancel
Save