RED-6774 - updated details radio component
This commit is contained in:
parent
88babfd1f6
commit
afbfaf2959
@ -25,9 +25,9 @@ export abstract class BaseDialogComponent implements AfterViewInit, OnDestroy {
|
|||||||
protected readonly _formBuilder = inject(UntypedFormBuilder);
|
protected readonly _formBuilder = inject(UntypedFormBuilder);
|
||||||
protected readonly _loadingService = inject(LoadingService);
|
protected readonly _loadingService = inject(LoadingService);
|
||||||
protected readonly _toaster = inject(Toaster);
|
protected readonly _toaster = inject(Toaster);
|
||||||
|
protected readonly _subscriptions: Subscription = new Subscription();
|
||||||
readonly #confirmationDialogService = inject(ConfirmationDialogService);
|
readonly #confirmationDialogService = inject(ConfirmationDialogService);
|
||||||
readonly #dialog = inject(MatDialog);
|
readonly #dialog = inject(MatDialog);
|
||||||
readonly #subscriptions: Subscription = new Subscription();
|
|
||||||
#hasErrors = false;
|
#hasErrors = false;
|
||||||
|
|
||||||
protected constructor(protected readonly _dialogRef: MatDialogRef<BaseDialogComponent>, private readonly _isInEditMode = false) {}
|
protected constructor(protected readonly _dialogRef: MatDialogRef<BaseDialogComponent>, private readonly _isInEditMode = false) {}
|
||||||
@ -45,20 +45,20 @@ export abstract class BaseDialogComponent implements AfterViewInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
this.#subscriptions.add(this._dialogRef.backdropClick().subscribe(() => this.close()));
|
this._subscriptions.add(this._dialogRef.backdropClick().subscribe(() => this.close()));
|
||||||
|
|
||||||
const events = [fromEvent(window, 'keyup'), fromEvent(window, 'input'), this.form?.valueChanges];
|
const events = [fromEvent(window, 'keyup'), fromEvent(window, 'input'), this.form?.valueChanges];
|
||||||
const events$ = merge(...events).pipe(
|
const events$ = merge(...events).pipe(
|
||||||
debounceTime(10),
|
debounceTime(10),
|
||||||
tap(() => (this.#hasErrors = !!document.getElementsByClassName('ng-invalid')[0])),
|
tap(() => (this.#hasErrors = !!document.getElementsByClassName('ng-invalid')[0])),
|
||||||
);
|
);
|
||||||
this.#subscriptions.add(events$.subscribe());
|
this._subscriptions.add(events$.subscribe());
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract save(options?: SaveOptions): void;
|
abstract save(options?: SaveOptions): void;
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.#subscriptions.unsubscribe();
|
this._subscriptions.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
|
|||||||
@ -1,6 +1,14 @@
|
|||||||
|
interface ExtraOption {
|
||||||
|
label: string;
|
||||||
|
checked: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface DetailsRadioOption<I> {
|
export interface DetailsRadioOption<I> {
|
||||||
id?: string;
|
id?: string;
|
||||||
label: string;
|
label: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
descriptionParams?: Record<string, string>;
|
||||||
|
icon?: string;
|
||||||
value: I;
|
value: I;
|
||||||
|
extraOption?: ExtraOption;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,11 +7,35 @@
|
|||||||
[ngClass]="{ 'mb-8': !displayInRow, 'mr-8': displayInRow }"
|
[ngClass]="{ 'mb-8': !displayInRow, 'mr-8': displayInRow }"
|
||||||
class="option pointer"
|
class="option pointer"
|
||||||
>
|
>
|
||||||
<div class="flex-align-items-center mb-8">
|
<div class="icon-option" *ngIf="option.icon; else withoutIcon">
|
||||||
<iqser-round-checkbox [active]="option.value === value?.value" class="mr-6"></iqser-round-checkbox>
|
<mat-icon class="icon" [svgIcon]="option.icon"></mat-icon>
|
||||||
<label class="details-radio-label pointer">{{ option.label | translate }}</label>
|
|
||||||
|
<div class="text">
|
||||||
|
<label class="details-radio-label pointer">{{ option.label | translate }}</label>
|
||||||
|
<span class="hint" [innerHTML]="option.description | translate : option.descriptionParams"></span>
|
||||||
|
|
||||||
|
<div class="iqser-input-group" *ngIf="option.extraOption && isSelected(option)">
|
||||||
|
<mat-checkbox
|
||||||
|
color="primary"
|
||||||
|
[(ngModel)]="option.extraOption.checked"
|
||||||
|
[checked]="option.extraOption.checked"
|
||||||
|
(change)="emitExtraOption()"
|
||||||
|
>
|
||||||
|
{{ option.extraOption.label | translate }}
|
||||||
|
</mat-checkbox>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<mat-icon *ngIf="isSelected(option)" class="checked" svgIcon="iqser:radio-selected"></mat-icon>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="hint">{{ option.description | translate }}</span>
|
<ng-template #withoutIcon>
|
||||||
|
<div class="flex-align-items-center mb-8">
|
||||||
|
<iqser-round-checkbox [active]="isSelected(option)" class="mr-6"></iqser-round-checkbox>
|
||||||
|
<label class="details-radio-label pointer">{{ option.label | translate }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span class="hint">{{ option.description | translate }}</span>
|
||||||
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -10,6 +10,28 @@ label {
|
|||||||
&.active {
|
&.active {
|
||||||
background-color: rgba(var(--iqser-primary-rgb), 0.1);
|
background-color: rgba(var(--iqser-primary-rgb), 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-option {
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
transform: scale(1.2);
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checked {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-top: 5px;
|
||||||
|
transform: scale(0.8);
|
||||||
|
color: var(--iqser-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.row {
|
.row {
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
import { Component, Input } from '@angular/core';
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
import { DetailsRadioOption } from './details-radio-option';
|
import { DetailsRadioOption } from './details-radio-option';
|
||||||
import { NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';
|
import { FormsModule, NG_VALIDATORS, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { FormFieldComponent } from '../form-field/form-field-component.directive';
|
import { FormFieldComponent } from '../form-field/form-field-component.directive';
|
||||||
import { NgClass, NgForOf } from '@angular/common';
|
import { NgClass, NgForOf, NgIf } from '@angular/common';
|
||||||
import { RoundCheckboxComponent } from '../round-checkbox/round-checkbox.component';
|
import { RoundCheckboxComponent } from '../round-checkbox/round-checkbox.component';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'iqser-details-radio [options]',
|
selector: 'iqser-details-radio [options]',
|
||||||
@ -23,20 +25,42 @@ import { TranslateModule } from '@ngx-translate/core';
|
|||||||
useExisting: DetailsRadioComponent,
|
useExisting: DetailsRadioComponent,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
imports: [NgForOf, NgClass, RoundCheckboxComponent, TranslateModule],
|
imports: [
|
||||||
|
NgForOf,
|
||||||
|
NgClass,
|
||||||
|
RoundCheckboxComponent,
|
||||||
|
TranslateModule,
|
||||||
|
MatIconModule,
|
||||||
|
NgIf,
|
||||||
|
FormsModule,
|
||||||
|
MatCheckboxModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class DetailsRadioComponent<I> extends FormFieldComponent<DetailsRadioOption<I>> {
|
export class DetailsRadioComponent<I> extends FormFieldComponent<DetailsRadioOption<I>> {
|
||||||
@Input() options: DetailsRadioOption<I>[] = [];
|
@Input() options: DetailsRadioOption<I>[] = [];
|
||||||
@Input() displayInRow = false;
|
@Input() displayInRow = false;
|
||||||
|
|
||||||
|
@Output() readonly extraOptionChanged: EventEmitter<DetailsRadioOption<I>> = new EventEmitter();
|
||||||
|
|
||||||
toggleOption(option: DetailsRadioOption<I>): void {
|
toggleOption(option: DetailsRadioOption<I>): void {
|
||||||
this.markAsTouched();
|
if (option.value !== this._value?.value) {
|
||||||
const currentlyChecked = this.value?.value === option.value;
|
this.markAsTouched();
|
||||||
this._value = currentlyChecked ? undefined : option;
|
const currentlyChecked = this.value?.value === option.value;
|
||||||
this.onChange(this._value);
|
this._value = currentlyChecked ? undefined : option;
|
||||||
|
this.onChange(this._value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
groupId(option: DetailsRadioOption<I>) {
|
groupId(option: DetailsRadioOption<I>): string {
|
||||||
return (option.id ?? option.label.replace('.', '-')) + '-checkbox-details-input';
|
return (option.id ?? option.label.replace('.', '-')) + '-checkbox-details-input';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isSelected(option: DetailsRadioOption<I>): boolean {
|
||||||
|
return option.value === this.value?.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
emitExtraOption(): void {
|
||||||
|
this.extraOptionChanged.emit(this.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user