@@ -6,6 +6,7 @@ import 'dart:async';
66
77import 'package:angular/angular.dart' ;
88import 'package:angular_forms/angular_forms.dart' ;
9+ import 'package:fixnum/fixnum.dart' ;
910import 'package:intl/intl.dart' ;
1011import 'package:quiver/strings.dart' ;
1112import '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)
172241class 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)
199267class 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