@libs-ui/pipes-format-number 0.2.356-41 → 0.2.356-43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +186 -72
- package/fesm2022/libs-ui-pipes-format-number.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,14 +1,27 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @libs-ui/pipes-format-number
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Angular pipe format số theo ngôn ngữ (EN/VI) với phân cách hàng nghìn, số thập phân và kiểm soát số âm.
|
|
4
|
+
|
|
5
|
+
## Giới thiệu
|
|
6
|
+
|
|
7
|
+
`LibsUiPipesFormatNumberPipe` là một Angular standalone pipe giúp hiển thị số theo chuẩn locale EN hoặc VI. Pipe tự động detect ngôn ngữ từ `UtilsCache` hoặc nhận ngôn ngữ trực tiếp qua tham số. Bên trong là thin wrapper của hàm `viewDataNumberByLanguage` từ `@libs-ui/utils`, vì vậy khi cần dùng trong TypeScript thì gọi thẳng hàm đó mà không cần inject pipe.
|
|
4
8
|
|
|
5
9
|
## Tính năng
|
|
6
10
|
|
|
7
|
-
- ✅
|
|
8
|
-
- ✅ Định dạng số thập phân với số chữ số tùy chỉnh
|
|
9
|
-
- ✅
|
|
10
|
-
- ✅
|
|
11
|
-
- ✅ Hỗ trợ truyền ngôn ngữ trực tiếp vào pipe (
|
|
11
|
+
- ✅ Phân cách hàng nghìn theo locale: dấu `.` cho VI, dấu `,` cho EN
|
|
12
|
+
- ✅ Định dạng số thập phân với số chữ số tùy chỉnh (`parseFixed`)
|
|
13
|
+
- ✅ Kiểm soát số âm — `acceptNegativeValue: false` trả về `0` thay vì hiển thị số âm
|
|
14
|
+
- ✅ Tự động detect ngôn ngữ từ `UtilsCache` nếu không truyền tham số `lang`
|
|
15
|
+
- ✅ Hỗ trợ truyền ngôn ngữ trực tiếp vào pipe (`'en'` hoặc `'vi'`)
|
|
16
|
+
- ✅ Chấp nhận cả `number` và `string` làm giá trị đầu vào
|
|
17
|
+
- ✅ Standalone pipe — import trực tiếp vào component, không cần NgModule
|
|
18
|
+
|
|
19
|
+
## Khi nào sử dụng
|
|
20
|
+
|
|
21
|
+
- Hiển thị số tiền, giá cả với định dạng phân cách hàng nghìn chuẩn locale
|
|
22
|
+
- Format số thập phân theo chuẩn ngôn ngữ (EN: `1,234,567.89` — VI: `1.234.567,89`)
|
|
23
|
+
- Cần kiểm soát hành vi khi giá trị âm (ẩn số âm, hiển thị 0 thay thế)
|
|
24
|
+
- Chuyển đổi giữa định dạng số có dấu phân cách và số thuần trong cùng template
|
|
12
25
|
|
|
13
26
|
## Cài đặt
|
|
14
27
|
|
|
@@ -16,113 +29,214 @@ Pipe format số theo ngôn ngữ (EN/VI) với hỗ trợ phân cách hàng ngh
|
|
|
16
29
|
npm install @libs-ui/pipes-format-number
|
|
17
30
|
```
|
|
18
31
|
|
|
19
|
-
##
|
|
32
|
+
## Import
|
|
20
33
|
|
|
21
|
-
|
|
34
|
+
```typescript
|
|
35
|
+
import { LibsUiPipesFormatNumberPipe } from '@libs-ui/pipes-format-number';
|
|
36
|
+
|
|
37
|
+
// Dùng trong component
|
|
38
|
+
@Component({
|
|
39
|
+
standalone: true,
|
|
40
|
+
imports: [LibsUiPipesFormatNumberPipe],
|
|
41
|
+
// ...
|
|
42
|
+
})
|
|
43
|
+
export class MyComponent {}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Nếu cần dùng trong TypeScript (computed, service), import thẳng hàm utils — không cần inject pipe:
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { viewDataNumberByLanguage } from '@libs-ui/utils';
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Ví dụ sử dụng
|
|
53
|
+
|
|
54
|
+
### Ví dụ 1 — Format cơ bản (tự động detect ngôn ngữ)
|
|
22
55
|
|
|
23
56
|
```typescript
|
|
57
|
+
import { Component } from '@angular/core';
|
|
24
58
|
import { LibsUiPipesFormatNumberPipe } from '@libs-ui/pipes-format-number';
|
|
25
|
-
import { UtilsLanguageConstants } from '@libs-ui/utils';
|
|
26
59
|
|
|
27
60
|
@Component({
|
|
28
|
-
selector: 'app-
|
|
61
|
+
selector: 'app-price-display',
|
|
29
62
|
standalone: true,
|
|
30
63
|
imports: [LibsUiPipesFormatNumberPipe],
|
|
31
64
|
template: `
|
|
32
65
|
<!-- Tự động detect ngôn ngữ từ UtilsCache -->
|
|
33
|
-
<p>
|
|
34
|
-
<!-- Output: 1.234.567
|
|
66
|
+
<p>Giá: {{ 1234567 | LibsUiPipesFormatNumberPipe:true:2 }}</p>
|
|
67
|
+
<!-- Output VI: 1.234.567 -->
|
|
68
|
+
<!-- Output EN: 1,234,567 -->
|
|
69
|
+
`,
|
|
70
|
+
})
|
|
71
|
+
export class PriceDisplayComponent {}
|
|
72
|
+
```
|
|
35
73
|
|
|
36
|
-
|
|
37
|
-
<p>EN: {{ 1234567 | LibsUiPipesFormatNumberPipe: true : 2 : true : false : 'en' }}</p>
|
|
38
|
-
<!-- Output: 1,234,567 -->
|
|
74
|
+
### Ví dụ 2 — Truyền ngôn ngữ trực tiếp
|
|
39
75
|
|
|
40
|
-
|
|
41
|
-
|
|
76
|
+
```typescript
|
|
77
|
+
import { Component } from '@angular/core';
|
|
78
|
+
import { LibsUiPipesFormatNumberPipe } from '@libs-ui/pipes-format-number';
|
|
79
|
+
|
|
80
|
+
@Component({
|
|
81
|
+
selector: 'app-price-locale',
|
|
82
|
+
standalone: true,
|
|
83
|
+
imports: [LibsUiPipesFormatNumberPipe],
|
|
84
|
+
template: `
|
|
85
|
+
<p>EN: {{ 1234567.89 | LibsUiPipesFormatNumberPipe:true:2:true:false:'en' }}</p>
|
|
86
|
+
<!-- Output: 1,234,567.89 -->
|
|
87
|
+
|
|
88
|
+
<p>VI: {{ 1234567.89 | LibsUiPipesFormatNumberPipe:true:2:true:false:'vi' }}</p>
|
|
89
|
+
<!-- Output: 1.234.567,89 -->
|
|
42
90
|
`,
|
|
43
91
|
})
|
|
44
|
-
export class
|
|
45
|
-
readonly EN = UtilsLanguageConstants.EN;
|
|
46
|
-
readonly VI = UtilsLanguageConstants.VI;
|
|
47
|
-
}
|
|
92
|
+
export class PriceLocaleComponent {}
|
|
48
93
|
```
|
|
49
94
|
|
|
50
|
-
###
|
|
51
|
-
|
|
52
|
-
Pipe là thin wrapper của hàm `viewDataNumberByLanguage` trong `@libs-ui/utils`. Khi cần gọi trong TypeScript, import và dùng thẳng hàm đó — **không cần inject pipe**:
|
|
95
|
+
### Ví dụ 3 — Kiểm soát số âm
|
|
53
96
|
|
|
54
97
|
```typescript
|
|
55
|
-
import {
|
|
98
|
+
import { Component } from '@angular/core';
|
|
99
|
+
import { LibsUiPipesFormatNumberPipe } from '@libs-ui/pipes-format-number';
|
|
56
100
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
101
|
+
@Component({
|
|
102
|
+
selector: 'app-balance-display',
|
|
103
|
+
standalone: true,
|
|
104
|
+
imports: [LibsUiPipesFormatNumberPipe],
|
|
105
|
+
template: `
|
|
106
|
+
<!-- Hiển thị số âm bình thường -->
|
|
107
|
+
<p>Số dư: {{ -5000.5 | LibsUiPipesFormatNumberPipe:true:2 }}</p>
|
|
108
|
+
<!-- Output VI: -5.000,5 -->
|
|
60
109
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
110
|
+
<!-- Ẩn số âm, trả về 0 -->
|
|
111
|
+
<p>Số dư tối thiểu: {{ -5000.5 | LibsUiPipesFormatNumberPipe:false:2 }}</p>
|
|
112
|
+
<!-- Output: 0 -->
|
|
113
|
+
`,
|
|
114
|
+
})
|
|
115
|
+
export class BalanceDisplayComponent {}
|
|
116
|
+
```
|
|
64
117
|
|
|
65
|
-
|
|
66
|
-
|
|
118
|
+
### Ví dụ 4 — Dùng trong TypeScript (không cần inject pipe)
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
import { Component, computed, signal } from '@angular/core';
|
|
122
|
+
import { viewDataNumberByLanguage } from '@libs-ui/utils';
|
|
123
|
+
|
|
124
|
+
@Component({
|
|
125
|
+
selector: 'app-invoice',
|
|
126
|
+
standalone: true,
|
|
127
|
+
template: `<p>Tổng tiền: {{ totalFormatted() }}</p>`,
|
|
128
|
+
})
|
|
129
|
+
export class InvoiceComponent {
|
|
130
|
+
private readonly total = signal<number>(9876543.123);
|
|
131
|
+
|
|
132
|
+
// Dùng thẳng hàm utils trong computed — không inject pipe
|
|
133
|
+
protected totalFormatted = computed(() =>
|
|
134
|
+
viewDataNumberByLanguage(this.total(), true, 2, true, false, 'vi')
|
|
135
|
+
);
|
|
136
|
+
// Output: 9.876.543,12
|
|
137
|
+
}
|
|
67
138
|
```
|
|
68
139
|
|
|
69
|
-
|
|
140
|
+
### Ví dụ 5 — Số thập phân với parseFixed
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
import { Component } from '@angular/core';
|
|
144
|
+
import { LibsUiPipesFormatNumberPipe } from '@libs-ui/pipes-format-number';
|
|
145
|
+
|
|
146
|
+
@Component({
|
|
147
|
+
selector: 'app-rate-display',
|
|
148
|
+
standalone: true,
|
|
149
|
+
imports: [LibsUiPipesFormatNumberPipe],
|
|
150
|
+
template: `
|
|
151
|
+
<!-- 1 chữ số thập phân (mặc định) -->
|
|
152
|
+
<p>{{ 1234.5678 | LibsUiPipesFormatNumberPipe:true:1 }}</p>
|
|
153
|
+
<!-- Output VI: 1.234,5 -->
|
|
154
|
+
|
|
155
|
+
<!-- 3 chữ số thập phân -->
|
|
156
|
+
<p>{{ 1234.5678 | LibsUiPipesFormatNumberPipe:true:3 }}</p>
|
|
157
|
+
<!-- Output VI: 1.234,567 -->
|
|
70
158
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
159
|
+
<!-- Không có thập phân -->
|
|
160
|
+
<p>{{ 1234.5678 | LibsUiPipesFormatNumberPipe:true:0 }}</p>
|
|
161
|
+
<!-- Output VI: 1.234 -->
|
|
162
|
+
`,
|
|
163
|
+
})
|
|
164
|
+
export class RateDisplayComponent {}
|
|
165
|
+
```
|
|
75
166
|
|
|
76
|
-
##
|
|
167
|
+
## Transform (Pipe)
|
|
77
168
|
|
|
78
|
-
###
|
|
169
|
+
### Tên pipe
|
|
79
170
|
|
|
80
171
|
```
|
|
81
172
|
LibsUiPipesFormatNumberPipe
|
|
82
173
|
```
|
|
83
174
|
|
|
84
|
-
###
|
|
175
|
+
### Cú pháp
|
|
85
176
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
| lang | `string` | `undefined` | Ngôn ngữ format (`'en'` hoặc `'vi'`). Nếu không truyền, tự động detect từ UtilsCache |
|
|
177
|
+
```html
|
|
178
|
+
{{ value | LibsUiPipesFormatNumberPipe : acceptNegativeValue }}
|
|
179
|
+
{{ value | LibsUiPipesFormatNumberPipe : acceptNegativeValue : parseFixed }}
|
|
180
|
+
{{ value | LibsUiPipesFormatNumberPipe : acceptNegativeValue : parseFixed : ignoreFormatSeparator }}
|
|
181
|
+
{{ value | LibsUiPipesFormatNumberPipe : acceptNegativeValue : parseFixed : ignoreFormatSeparator : ignoreParseFloat }}
|
|
182
|
+
{{ value | LibsUiPipesFormatNumberPipe : acceptNegativeValue : parseFixed : ignoreFormatSeparator : ignoreParseFloat : lang }}
|
|
183
|
+
```
|
|
94
184
|
|
|
95
|
-
###
|
|
185
|
+
### Tham số
|
|
96
186
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
187
|
+
| Tham số | Type | Bắt buộc | Default | Mô tả | Ví dụ |
|
|
188
|
+
|---|---|---|---|---|---|
|
|
189
|
+
| `value` | `number \| string` | Có | — | Giá trị cần format | `1234567.89` |
|
|
190
|
+
| `acceptNegativeValue` | `boolean` | Có | — | Cho phép giá trị âm. Nếu `false`, giá trị âm trả về `0` | `true` |
|
|
191
|
+
| `parseFixed` | `number` | Không | `1` | Số chữ số thập phân tối đa | `2` |
|
|
192
|
+
| `ignoreFormatSeparator` | `boolean` | Không | `true` | Bỏ qua dấu phân cách có sẵn trong chuỗi đầu vào trước khi format | `false` |
|
|
193
|
+
| `ignoreParseFloat` | `boolean` | Không | `undefined` | Không parse float, giữ nguyên chuỗi thập phân gốc | `false` |
|
|
194
|
+
| `lang` | `string` | Không | `undefined` | Ngôn ngữ format: `'en'` hoặc `'vi'`. Nếu không truyền, tự động detect từ `UtilsCache` | `'vi'` |
|
|
100
195
|
|
|
101
|
-
|
|
102
|
-
{{ value | LibsUiPipesFormatNumberPipe:acceptNegativeValue:2 }}
|
|
196
|
+
### Quy tắc format theo ngôn ngữ
|
|
103
197
|
|
|
104
|
-
|
|
105
|
-
|
|
198
|
+
| Ngôn ngữ | Phân cách hàng nghìn | Phân cách thập phân | Ví dụ (1234567.89) |
|
|
199
|
+
|---|---|---|---|
|
|
200
|
+
| `'en'` | `,` | `.` | `1,234,567.89` |
|
|
201
|
+
| `'vi'` | `.` | `,` | `1.234.567,89` |
|
|
106
202
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
```
|
|
203
|
+
### Dùng trong TypeScript (standalone)
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
import { viewDataNumberByLanguage } from '@libs-ui/utils';
|
|
110
207
|
|
|
111
|
-
|
|
208
|
+
// Tự động detect ngôn ngữ từ UtilsCache
|
|
209
|
+
const result = viewDataNumberByLanguage(1234567.89, true, 2);
|
|
210
|
+
// Output VI: '1.234.567,89'
|
|
112
211
|
|
|
113
|
-
|
|
212
|
+
// Truyền ngôn ngữ cụ thể
|
|
213
|
+
const resultEN = viewDataNumberByLanguage(1234567.89, true, 2, true, false, 'en');
|
|
214
|
+
// Output: '1,234,567.89'
|
|
114
215
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
216
|
+
const resultVI = viewDataNumberByLanguage(1234567.89, true, 2, true, false, 'vi');
|
|
217
|
+
// Output: '1.234.567,89'
|
|
218
|
+
|
|
219
|
+
// Số âm với acceptNegativeValue = false
|
|
220
|
+
const noNegative = viewDataNumberByLanguage(-5000, false, 2);
|
|
221
|
+
// Output: '0'
|
|
119
222
|
```
|
|
120
223
|
|
|
121
|
-
##
|
|
224
|
+
## Lưu ý quan trọng
|
|
225
|
+
|
|
226
|
+
⚠️ **Thứ tự tham số positional**: Pipe dùng positional arguments, không phải named. Muốn truyền `lang` thì phải truyền đủ cả `ignoreFormatSeparator` và `ignoreParseFloat` trước đó: `{{ value | LibsUiPipesFormatNumberPipe:true:2:true:false:'vi' }}`.
|
|
227
|
+
|
|
228
|
+
⚠️ **acceptNegativeValue là bắt buộc**: Tham số này luôn phải được truyền (không có default). Thiếu tham số này pipe sẽ nhận `undefined` và hành vi không xác định.
|
|
229
|
+
|
|
230
|
+
⚠️ **Detect ngôn ngữ tự động**: Khi không truyền `lang`, pipe gọi `UtilsCache.getLang()` để detect ngôn ngữ hiện tại của ứng dụng. Đảm bảo `UtilsCache` đã được khởi tạo với ngôn ngữ đúng trước khi render.
|
|
122
231
|
|
|
123
|
-
|
|
124
|
-
- **Production**: (sau khi deploy)
|
|
232
|
+
⚠️ **Dùng trong TypeScript — không inject pipe**: Pipe là thin wrapper. Khi cần format trong `.ts` (service, computed, resolver), hãy import thẳng `viewDataNumberByLanguage` từ `@libs-ui/utils` thay vì inject `LibsUiPipesFormatNumberPipe`.
|
|
125
233
|
|
|
126
|
-
|
|
234
|
+
⚠️ **parseFixed và trailing zeros**: `parseFixed` là số chữ số thập phân tối đa, không phải cố định. Số `1234.5` với `parseFixed: 3` có thể cho ra `1.234,5` (không padding thêm `0`).
|
|
235
|
+
|
|
236
|
+
## Demo
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
npx nx serve core-ui
|
|
240
|
+
```
|
|
127
241
|
|
|
128
|
-
|
|
242
|
+
Truy cập: http://localhost:4500/pipes/format-number
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"libs-ui-pipes-format-number.mjs","sources":["../../../../../libs-ui/pipes/format-number/src/format-number.pipe.ts","../../../../../libs-ui/pipes/format-number/src/libs-ui-pipes-format-number.ts"],"sourcesContent":["import { Pipe, PipeTransform } from '@angular/core';\nimport { viewDataNumberByLanguage } from '@libs-ui/utils';\n\n@Pipe({\n name: 'LibsUiPipesFormatNumberPipe',\n standalone: true,\n})\nexport class LibsUiPipesFormatNumberPipe implements PipeTransform {\n transform(value: number | string, acceptNegativeValue: boolean, parseFixed = 1, ignoreFormatSeparator = true, ignoreParseFloat?: boolean, lang?: string) {\n return viewDataNumberByLanguage(value, acceptNegativeValue, parseFixed, ignoreFormatSeparator, ignoreParseFloat, lang);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;MAOa,2BAA2B,CAAA;AACtC,IAAA,SAAS,CAAC,KAAsB,EAAE,mBAA4B,EAAE,UAAU,GAAG,CAAC,EAAE,qBAAqB,GAAG,IAAI,EAAE,gBAA0B,EAAE,IAAa,EAAA;AACrJ,QAAA,OAAO,wBAAwB,CAAC,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"libs-ui-pipes-format-number.mjs","sources":["../../../../../libs-ui/pipes/format-number/src/format-number.pipe.ts","../../../../../libs-ui/pipes/format-number/src/libs-ui-pipes-format-number.ts"],"sourcesContent":["import { Pipe, PipeTransform } from '@angular/core';\nimport { viewDataNumberByLanguage } from '@libs-ui/utils';\n\n@Pipe({\n name: 'LibsUiPipesFormatNumberPipe',\n standalone: true,\n})\nexport class LibsUiPipesFormatNumberPipe implements PipeTransform {\n transform(value: number | string, acceptNegativeValue: boolean, parseFixed = 1, ignoreFormatSeparator = true, ignoreParseFloat?: boolean, lang?: string) {\n return viewDataNumberByLanguage(value, acceptNegativeValue, parseFixed, ignoreFormatSeparator, ignoreParseFloat, lang);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;MAOa,2BAA2B,CAAA;AACtC,IAAA,SAAS,CAAC,KAAsB,EAAE,mBAA4B,EAAE,UAAU,GAAG,CAAC,EAAE,qBAAqB,GAAG,IAAI,EAAE,gBAA0B,EAAE,IAAa,EAAA;AACrJ,QAAA,OAAO,wBAAwB,CAAC,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,IAAI,CAAC,CAAC;KACxH;wGAHU,2BAA2B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,IAAA,EAAA,CAAA,CAAA;sGAA3B,2BAA2B,EAAA,YAAA,EAAA,IAAA,EAAA,IAAA,EAAA,6BAAA,EAAA,CAAA,CAAA;;4FAA3B,2BAA2B,EAAA,UAAA,EAAA,CAAA;kBAJvC,IAAI;AAAC,YAAA,IAAA,EAAA,CAAA;AACJ,oBAAA,IAAI,EAAE,6BAA6B;AACnC,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA,CAAA;;;ACND;;AAEG;;;;"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libs-ui/pipes-format-number",
|
|
3
|
-
"version": "0.2.356-
|
|
3
|
+
"version": "0.2.356-43",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/core": ">=18.0.0",
|
|
6
|
-
"@libs-ui/utils": "0.2.356-
|
|
6
|
+
"@libs-ui/utils": "0.2.356-43"
|
|
7
7
|
},
|
|
8
8
|
"sideEffects": false,
|
|
9
9
|
"module": "fesm2022/libs-ui-pipes-format-number.mjs",
|