|
@@ -4,12 +4,13 @@ import {
|
|
|
EventEmitter,
|
|
EventEmitter,
|
|
|
Input,
|
|
Input,
|
|
|
OnChanges,
|
|
OnChanges,
|
|
|
|
|
+ OnDestroy,
|
|
|
OnInit,
|
|
OnInit,
|
|
|
Output,
|
|
Output,
|
|
|
SimpleChanges,
|
|
SimpleChanges,
|
|
|
} from '@angular/core';
|
|
} from '@angular/core';
|
|
|
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
|
-import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
|
|
|
|
|
|
|
+import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs';
|
|
|
import { map } from 'rxjs/operators';
|
|
import { map } from 'rxjs/operators';
|
|
|
|
|
|
|
|
import { DataService } from '../../../data/providers/data.service';
|
|
import { DataService } from '../../../data/providers/data.service';
|
|
@@ -30,7 +31,7 @@ import { DataService } from '../../../data/providers/data.service';
|
|
|
},
|
|
},
|
|
|
],
|
|
],
|
|
|
})
|
|
})
|
|
|
-export class CurrencyInputComponent implements ControlValueAccessor, OnInit, OnChanges {
|
|
|
|
|
|
|
+export class CurrencyInputComponent implements ControlValueAccessor, OnInit, OnChanges, OnDestroy {
|
|
|
@Input() disabled = false;
|
|
@Input() disabled = false;
|
|
|
@Input() readonly = false;
|
|
@Input() readonly = false;
|
|
|
@Input() value: number;
|
|
@Input() value: number;
|
|
@@ -38,10 +39,12 @@ export class CurrencyInputComponent implements ControlValueAccessor, OnInit, OnC
|
|
|
@Output() valueChange = new EventEmitter();
|
|
@Output() valueChange = new EventEmitter();
|
|
|
prefix$: Observable<string>;
|
|
prefix$: Observable<string>;
|
|
|
suffix$: Observable<string>;
|
|
suffix$: Observable<string>;
|
|
|
|
|
+ hasFractionPart = true;
|
|
|
onChange: (val: any) => void;
|
|
onChange: (val: any) => void;
|
|
|
onTouch: () => void;
|
|
onTouch: () => void;
|
|
|
- _decimalValue: string;
|
|
|
|
|
|
|
+ _inputValue: string;
|
|
|
private currencyCode$ = new BehaviorSubject<string>('');
|
|
private currencyCode$ = new BehaviorSubject<string>('');
|
|
|
|
|
+ private subscription: Subscription;
|
|
|
|
|
|
|
|
constructor(private dataService: DataService, private changeDetectorRef: ChangeDetectorRef) {}
|
|
constructor(private dataService: DataService, private changeDetectorRef: ChangeDetectorRef) {}
|
|
|
|
|
|
|
@@ -53,11 +56,13 @@ export class CurrencyInputComponent implements ControlValueAccessor, OnInit, OnC
|
|
|
return '';
|
|
return '';
|
|
|
}
|
|
}
|
|
|
const locale = languageCode.replace(/_/g, '-');
|
|
const locale = languageCode.replace(/_/g, '-');
|
|
|
- const parts = (new Intl.NumberFormat(locale, {
|
|
|
|
|
- style: 'currency',
|
|
|
|
|
- currency: currencyCode,
|
|
|
|
|
- currencyDisplay: 'symbol',
|
|
|
|
|
- }) as any).formatToParts();
|
|
|
|
|
|
|
+ const parts = (
|
|
|
|
|
+ new Intl.NumberFormat(locale, {
|
|
|
|
|
+ style: 'currency',
|
|
|
|
|
+ currency: currencyCode,
|
|
|
|
|
+ currencyDisplay: 'symbol',
|
|
|
|
|
+ }) as any
|
|
|
|
|
+ ).formatToParts();
|
|
|
const NaNString = parts.find(p => p.type === 'nan')?.value ?? 'NaN';
|
|
const NaNString = parts.find(p => p.type === 'nan')?.value ?? 'NaN';
|
|
|
const localised = new Intl.NumberFormat(locale, {
|
|
const localised = new Intl.NumberFormat(locale, {
|
|
|
style: 'currency',
|
|
style: 'currency',
|
|
@@ -69,6 +74,24 @@ export class CurrencyInputComponent implements ControlValueAccessor, OnInit, OnC
|
|
|
);
|
|
);
|
|
|
this.prefix$ = shouldPrefix$.pipe(map(shouldPrefix => (shouldPrefix ? this.currencyCode : '')));
|
|
this.prefix$ = shouldPrefix$.pipe(map(shouldPrefix => (shouldPrefix ? this.currencyCode : '')));
|
|
|
this.suffix$ = shouldPrefix$.pipe(map(shouldPrefix => (shouldPrefix ? '' : this.currencyCode)));
|
|
this.suffix$ = shouldPrefix$.pipe(map(shouldPrefix => (shouldPrefix ? '' : this.currencyCode)));
|
|
|
|
|
+
|
|
|
|
|
+ this.subscription = combineLatest(languageCode$, this.currencyCode$).subscribe(
|
|
|
|
|
+ ([languageCode, currencyCode]) => {
|
|
|
|
|
+ if (!currencyCode) {
|
|
|
|
|
+ return '';
|
|
|
|
|
+ }
|
|
|
|
|
+ const locale = languageCode.replace(/_/g, '-');
|
|
|
|
|
+ const parts = (
|
|
|
|
|
+ new Intl.NumberFormat(locale, {
|
|
|
|
|
+ style: 'currency',
|
|
|
|
|
+ currency: currencyCode,
|
|
|
|
|
+ currencyDisplay: 'symbol',
|
|
|
|
|
+ }) as any
|
|
|
|
|
+ ).formatToParts(123.45);
|
|
|
|
|
+ this.hasFractionPart = !!parts.find(p => p.type === 'fraction');
|
|
|
|
|
+ this._inputValue = this.toNumericString(this._inputValue);
|
|
|
|
|
+ },
|
|
|
|
|
+ );
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ngOnChanges(changes: SimpleChanges) {
|
|
ngOnChanges(changes: SimpleChanges) {
|
|
@@ -80,6 +103,12 @@ export class CurrencyInputComponent implements ControlValueAccessor, OnInit, OnC
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ ngOnDestroy() {
|
|
|
|
|
+ if (this.subscription) {
|
|
|
|
|
+ this.subscription.unsubscribe();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
registerOnChange(fn: any) {
|
|
registerOnChange(fn: any) {
|
|
|
this.onChange = fn;
|
|
this.onChange = fn;
|
|
|
}
|
|
}
|
|
@@ -98,11 +127,11 @@ export class CurrencyInputComponent implements ControlValueAccessor, OnInit, OnC
|
|
|
this.onChange(integerValue);
|
|
this.onChange(integerValue);
|
|
|
}
|
|
}
|
|
|
this.valueChange.emit(integerValue);
|
|
this.valueChange.emit(integerValue);
|
|
|
- const delta = Math.abs(Number(this._decimalValue) - Number(value));
|
|
|
|
|
|
|
+ const delta = Math.abs(Number(this._inputValue) - Number(value));
|
|
|
if (0.009 < delta && delta < 0.011) {
|
|
if (0.009 < delta && delta < 0.011) {
|
|
|
- this._decimalValue = this.toNumericString(value);
|
|
|
|
|
|
|
+ this._inputValue = this.toNumericString(value);
|
|
|
} else {
|
|
} else {
|
|
|
- this._decimalValue = value;
|
|
|
|
|
|
|
+ this._inputValue = value;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -115,11 +144,11 @@ export class CurrencyInputComponent implements ControlValueAccessor, OnInit, OnC
|
|
|
writeValue(value: any): void {
|
|
writeValue(value: any): void {
|
|
|
const numericValue = +value;
|
|
const numericValue = +value;
|
|
|
if (!Number.isNaN(numericValue)) {
|
|
if (!Number.isNaN(numericValue)) {
|
|
|
- this._decimalValue = this.toNumericString(Math.floor(value) / 100);
|
|
|
|
|
|
|
+ this._inputValue = this.toNumericString(Math.floor(value) / 100);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private toNumericString(value: number | string): string {
|
|
private toNumericString(value: number | string): string {
|
|
|
- return Number(value).toFixed(2);
|
|
|
|
|
|
|
+ return this.hasFractionPart ? Number(value).toFixed(2) : Number(value).toFixed(0);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|