Skip to content
This repository was archived by the owner on May 20, 2023. It is now read-only.

Commit f141a54

Browse files
Googlernshahan
authored andcommitted
Create an Int64 value accessor for use with MaterialInput.
There is currently no number formatter specifically designed to handle Int64 values. If a user wants formatting for Int64 types, they must specifically bind their own - for example, the NumberFormat.decimalPattern() will work with Int64 values that you know will not overflow. PiperOrigin-RevId: 242511186
1 parent 96a58c1 commit f141a54

File tree

1 file changed

+86
-5
lines changed

1 file changed

+86
-5
lines changed

angular_components/lib/material_input/material_number_accessor.dart

Lines changed: 86 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'dart:async';
66

77
import 'package:angular/angular.dart';
88
import 'package:angular_forms/angular_forms.dart';
9+
import 'package:fixnum/fixnum.dart';
910
import 'package:intl/intl.dart';
1011
import 'package:quiver/strings.dart';
1112
import 'package:angular_components/utils/angular/properties/properties.dart';
@@ -23,6 +24,7 @@ const List<Type> materialNumberInputDirectives = [
2324
CheckIntegerValidator,
2425
LowerBoundValidator,
2526
MaterialInputComponent,
27+
MaterialInt64ValueAccessor,
2628
MaterialNumberValueAccessor,
2729
MaterialNumberValidator,
2830
PositiveNumValidator,
@@ -108,6 +110,75 @@ abstract class BaseMaterialNumberValueAccessor<T>
108110
}
109111
}
110112

113+
/// [ControlValueAccessor] which will coerce an input into an [Int64].
114+
///
115+
/// There is currently no Int64-specific formatter, so note that numberFormat
116+
/// cannot be safely used if your values are vulnerable to overflowing in size.
117+
///
118+
/// Use [materialNumberInputDirectives] to get a set of directives to use with
119+
/// the input to provide validations. Such as the default to ensure it is a
120+
/// number, `checkInteger`, `checkPositive`, `checkNonNegative` (allows 0,)
121+
/// `lowerBound`, and `upperBound`.
122+
///
123+
/// `keypressUpdate` attribute has the value update on every keypress while
124+
/// the default is the value only updating on a blur event.
125+
/// `blurFormat` attribute causes the input to be formatted on blur events.
126+
@Directive(
127+
selector: 'material-input[type=int64]',
128+
)
129+
class MaterialInt64ValueAccessor
130+
extends BaseMaterialNumberValueAccessor<Int64> {
131+
MaterialInt64ValueAccessor(
132+
BaseMaterialInput input,
133+
@Self() NgControl control,
134+
@Attribute('changeUpdate') String changeUpdateAttr,
135+
@Attribute('keypressUpdate') String keypressUpdateAttr,
136+
@Attribute('checkInteger') String checkInteger,
137+
@Attribute('blurFormat') String blurFormat,
138+
@Optional() NumberFormat numberFormat)
139+
: super(
140+
input,
141+
control,
142+
attributeToBool(changeUpdateAttr, defaultValue: false),
143+
attributeToBool(keypressUpdateAttr, defaultValue: false),
144+
attributeToBool(blurFormat, defaultValue: false),
145+
numberFormat) {
146+
assert(
147+
_checkValues(
148+
numberFormat, attributeToBool(blurFormat, defaultValue: false)),
149+
'You must supply a NumberFormat if using blurFormat');
150+
}
151+
152+
bool _checkValues(NumberFormat numberFormat, bool blurFormat) {
153+
if (numberFormat != null) {
154+
print('Warning: numberFormat only works with num and will overflow '
155+
'if the number is larger than a native int, even when using '
156+
'material-input[type=int64].');
157+
return blurFormat;
158+
}
159+
return true;
160+
}
161+
162+
@override
163+
Int64 parseNumber(String input) {
164+
if (input == null || input.isEmpty) {
165+
return null;
166+
}
167+
168+
try {
169+
// If using formatting, we must firsrt parse back to a non-formatted
170+
// String representation as Int64 cannot handle commas.
171+
if (_numberFormat != null) {
172+
input = _numberFormat.parse(input).toString();
173+
}
174+
175+
return Int64.parseInt(input);
176+
} on FormatException {
177+
return null;
178+
}
179+
}
180+
}
181+
111182
/// [ControlValueAccessor] which will coerce an input into a [num].
112183
///
113184
/// Use [materialNumberInputDirectives] to get a set of directives to use with
@@ -166,8 +237,6 @@ class MaterialNumberValueAccessor extends BaseMaterialNumberValueAccessor<num> {
166237
providers: [
167238
ExistingProvider.forToken(NG_VALIDATORS, MaterialNumberValidator)
168239
],
169-
// TODO(google): Change to `Visibility.local` to reduce code size.
170-
visibility: Visibility.all,
171240
)
172241
class MaterialNumberValidator implements Validator {
173242
/// Validation that works in concert with the number accessor.
@@ -191,10 +260,9 @@ class MaterialNumberValidator implements Validator {
191260
/// [Validator] which will validate a number input is an integer.
192261
@Directive(
193262
selector: 'material-input[type=number][checkInteger],'
194-
'material-input[type=percent][checkInteger]',
263+
'material-input[type=percent][checkInteger],'
264+
'material-input[type=int64]',
195265
providers: [ExistingProvider.forToken(NG_VALIDATORS, CheckIntegerValidator)],
196-
// TODO(google): Change to `Visibility.local` to reduce code size.
197-
visibility: Visibility.all,
198266
)
199267
class CheckIntegerValidator implements Validator {
200268
/// Validation that works in concert with the number accessor.
@@ -213,3 +281,16 @@ class CheckIntegerValidator implements Validator {
213281
desc: 'Error message when input number is not an integer.',
214282
meaning: 'Error message when input number is not an integer.');
215283
}
284+
285+
NumberFormat decimalNumberFormat() => NumberFormat.decimalPattern();
286+
287+
/// Helper directive to provide a basic [NumberFormat] pattern for use with
288+
/// number accessors.
289+
///
290+
/// This is not necessary for standard material-input[type=num] as it's provided
291+
/// as the default. It should only be used with material-input[type=int64].
292+
@Directive(
293+
selector: '[decimalNumberFormat]',
294+
providers: [Provider(NumberFormat, useFactory: decimalNumberFormat)],
295+
)
296+
class DecimalNumberFormatDirective {}

0 commit comments

Comments
 (0)