Reputation: 1067
I have created my text field which should only allow number input for the purpose of some computing i will later do after the value has been input. Its almost working fine but there is one issue though.
Here is the code for the field
var numberInputFormatters = [new FilteringTextInputFormatter.allow(RegExp("[0-9]")),];
String _tip='2';
Widget _buildOtherTipInput() {
return TextFormField(
style: inputTextStyle,
inputFormatters: numberInputFormatters,
keyboardType: TextInputType.number,
decoration: formInputDecoration.copyWith(
prefix: Text('\$'),
labelText: 'Enter Custom Tip Amount ',
hintStyle: TextStyle(fontWeight: FontWeight.w600)
),
onChanged: (val){
setState(() {
val!=null?_tip=val:_tip='0';
});
},
);
}
So when you input a number then try to input a non number character, it will not take the input but if i try to input a character that is not a number as the first, i get this error thrown
Invalid double
I do know that it comes from this code below that converts the string input to a double. What i don't understand is why it receives the invalid double in the first place yet i have set blockers for invalid(non number) input in my text field.
String getTotal(){
String theTip=_tip??'0';
double newTip = double.parse(theTip).truncateToDouble();
return newTip.toStringAsFixed(2);
}
Upvotes: 1
Views: 11367
Reputation: 8383
Your problem is that val
is never null
.
After inputting a wrong character, val
is ''
. You should check if it is empty:
onChanged: (val){
setState(() {
val.isNotEmpty ? _tip=val : _tip='0';
});
},
Instead of defining your own numberInputFormatters
, you should use FilteringTextInputFormatter.digitsOnly
.
Also, your _tip
is not a String
, you could store its value as an int
instead.
The, your onChanged
callback becomes:
onChanged: (val) => setState(() => _tip = int.tryParse(val) ?? 0),
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: MyWidget(price: 9.99),
),
);
}
class MyWidget extends StatefulWidget {
final double price;
const MyWidget({Key key, this.price}) : super(key: key);
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
int _tip = 2;
String get _total => (widget.price + _tip).toStringAsFixed(2);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
alignment: Alignment.center,
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Do you want to tip the waiter?'),
const SizedBox(height: 16.0),
TextFormField(
initialValue: _tip.toString(),
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
keyboardType: TextInputType.number,
decoration: InputDecoration(
prefix: Text('\$'),
labelText: 'Enter Custom Tip Amount ',
hintStyle: TextStyle(fontWeight: FontWeight.w600)),
onChanged: (val) => setState(() => _tip = int.tryParse(val) ?? 0),
),
const SizedBox(height: 16.0),
Text('TOTAL: $_total'),
],
),
),
);
}
}
Upvotes: 3
Reputation: 236
Consider using String Validator it is easy and simple to use
https://pub.dev/packages/string_validator
Upvotes: 1