@libs-ui/pipes-format-number 0.2.356-9 → 0.2.357-0

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 CHANGED
@@ -1,14 +1,27 @@
1
- # Format Number Pipe
1
+ # @libs-ui/pipes-format-number
2
2
 
3
- Pipe format số theo ngôn ngữ (EN/VI) với hỗ trợ phân cách hàng nghìn, số thập phân và số âm.
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
- - ✅ Format phân cách hàng nghìn (dấu `.` cho VI, dấu `,` cho EN)
8
- - ✅ Định dạng số thập phân với số chữ số tùy chỉnh
9
- - ✅ Hỗ trợ số âm với option kiểm soát
10
- - ✅ Chuyển đổi giữa định dạng số dấu phân cách số thuần
11
- - ✅ Hỗ trợ truyền ngôn ngữ trực tiếp vào pipe (EN/VI) hoặc tự động detect từ UtilsCache
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
- ## Sử dụng
32
+ ## Import
20
33
 
21
- ### Trong Template
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-example',
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>Số: {{ 1234567 | LibsUiPipesFormatNumberPipe: true : 2 }}</p>
34
- <!-- Output: 1.234.567 (VI) hoặc 1,234,567 (EN) -->
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
- <!-- Truyền ngôn ngữ trực tiếp -->
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
- <p>VI: {{ 1234567 | LibsUiPipesFormatNumberPipe: true : 2 : true : false : 'vi' }}</p>
41
- <!-- Output: 1.234.567 -->
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 ExampleComponent {
45
- readonly EN = UtilsLanguageConstants.EN;
46
- readonly VI = UtilsLanguageConstants.VI;
47
- }
92
+ export class PriceLocaleComponent {}
48
93
  ```
49
94
 
50
- ### Dùng trong TypeScript
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
+ ### dụ 3 — Kiểm soát số âm
53
96
 
54
97
  ```typescript
55
- import { viewDataNumberByLanguage, UtilsLanguageConstants } from '@libs-ui/utils';
98
+ import { Component } from '@angular/core';
99
+ import { LibsUiPipesFormatNumberPipe } from '@libs-ui/pipes-format-number';
56
100
 
57
- // Tự động detect ngôn ngữ từ UtilsCache
58
- const formatted = viewDataNumberByLanguage(1234567.89, true, 2);
59
- // Output: '1.234.567,89' (VI) hoặc '1,234,567.89' (EN)
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
- // Truyền ngôn ngữ trực tiếp
62
- const formattedEN = viewDataNumberByLanguage(1234567.89, true, 2, true, false, UtilsLanguageConstants.EN);
63
- // Output: '1,234,567.89'
110
+ <!-- Ẩn số âm, trả về 0 -->
111
+ <p>Số tối thiểu: {{ -5000.5 | LibsUiPipesFormatNumberPipe:false:2 }}</p>
112
+ <!-- Output: 0 -->
113
+ `,
114
+ })
115
+ export class BalanceDisplayComponent {}
116
+ ```
64
117
 
65
- const formattedVI = viewDataNumberByLanguage(1234567.89, true, 2, true, false, UtilsLanguageConstants.VI);
66
- // Output: '1.234.567,89'
118
+ ### 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
- ## Công nghệ sử dụng
140
+ ### 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
- | Công nghệ | tả |
72
- | -------------- | --------------------------------- |
73
- | Angular 18+ | Pipe transform với standalone API |
74
- | @libs-ui/utils | viewDataNumberByLanguage utility |
159
+ <!-- Không 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
- ## API Reference
167
+ ## Transform (Pipe)
77
168
 
78
- ### Pipe Name
169
+ ### Tên pipe
79
170
 
80
171
  ```
81
172
  LibsUiPipesFormatNumberPipe
82
173
  ```
83
174
 
84
- ### Parameters
175
+ ### Cú pháp
85
176
 
86
- | Parameter | Type | Default | Description |
87
- | --------------------- | ------------------ | ----------- | ------------------------------------------------------------------------------------ |
88
- | value | `number \| string` | required | Giá trị cần format |
89
- | acceptNegativeValue | `boolean` | required | Cho phép giá trị âm |
90
- | parseFixed | `number` | `1` | Số chữ số thập phân tối đa |
91
- | ignoreFormatSeparator | `boolean` | `true` | Bỏ qua format separator trong input string |
92
- | ignoreParseFloat | `boolean` | `undefined` | Không parse float |
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
- ### Usage Syntax
185
+ ### Tham số
96
186
 
97
- ```html
98
- <!-- Cơ bản - tự động detect ngôn ngữ từ UtilsCache -->
99
- {{ value | LibsUiPipesFormatNumberPipe:acceptNegativeValue }}
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
- <!-- Với parseFixed -->
102
- {{ value | LibsUiPipesFormatNumberPipe:acceptNegativeValue:2 }}
196
+ ### Quy tắc format theo ngôn ngữ
103
197
 
104
- <!-- Đầy đủ parameters -->
105
- {{ value | LibsUiPipesFormatNumberPipe:acceptNegativeValue:2:false:false }}
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
- <!-- Với ngôn ngữ cụ thể -->
108
- {{ value | LibsUiPipesFormatNumberPipe:acceptNegativeValue:2:true:false:'en' }} {{ value | LibsUiPipesFormatNumberPipe:acceptNegativeValue:2:true:false:'vi' }}
109
- ```
203
+ ### Dùng trong TypeScript (standalone)
204
+
205
+ ```typescript
206
+ import { viewDataNumberByLanguage } from '@libs-ui/utils';
110
207
 
111
- ## Unit Tests
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
- Xem chi tiết tại [test-commands.md](./test-commands.md)
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
- ```bash
116
- # Chạy test cho pipe này
117
- npx nx test pipes-format-number
118
- npx nx test pipes-format-number --no-cache
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
- ## Demo
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
- - **Local**: http://localhost:4500/pipes/format-number
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
- ## License
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
- MIT
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;IACxH;wGAHW,2BAA2B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,IAAA,EAAA,CAAA;sGAA3B,2BAA2B,EAAA,YAAA,EAAA,IAAA,EAAA,IAAA,EAAA,6BAAA,EAAA,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;;;ACND;;AAEG;;;;"}
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-9",
3
+ "version": "0.2.357-0",
4
4
  "peerDependencies": {
5
5
  "@angular/core": ">=18.0.0",
6
- "@libs-ui/utils": "0.2.356-9"
6
+ "@libs-ui/utils": "0.2.357-0"
7
7
  },
8
8
  "sideEffects": false,
9
9
  "module": "fesm2022/libs-ui-pipes-format-number.mjs",