我有一个带有一些输入的表格。我正在使用GlobalKey<FormState>
处理提交和验证等等。
其中一个字段应该接受双精度输入,因此我通过尝试将输入值解析为双精度来验证这一点:
return TextFormField(
decoration: InputDecoration(labelText: 'Price'),
keyboardType: TextInputType.number,
validator: (String value) {
double _parsedValue = double.tryParse(value);
if (_parsedValue == null) {
return "Please input a number";
}
},
onSaved: (String value) {
setState(() {
_price = double.parse(value);
});
},
);
现在可以正常工作了。但是,如果用户输入了9,99
,则可能会失败,因为解析期望9.99
。
我想做的是,当调用验证程序时,我想检查输入字符串中是否有任何逗号,如果存在,请用点代替它们,并相应地更新表单值
我的问题是-我们实际上可以从验证程序中更新表单状态吗?
答案 0 :(得分:0)
我认为也许您需要的是TextInputFormatter
。
这里是文档https://docs.flutter.io/flutter/services/TextInputFormatter-class.html
的链接有些预先存在的格式化程序可以用作将逗号转换为点的参考。
答案 1 :(得分:0)
我认为您不需要更新validator
中的状态。我只会使用save
事件来更新状态。这样,可以很清楚地知道状态在哪里更新。
我相信没有什么可以阻止您更新验证中的状态,但是也许它会变得井井有条。 :)
我想最好的方式来完成您需要的是将TextInputFormatter
与WhitelistingTextInputFormatter
一起使用,并检查一下:
请注意TextInputType.numberWithOptions(decimal: true)
,并且如果用户粘贴“ -100,00”,它将变为100.0-对于价格来说就可以了,但通常不建议使用double值
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'ValidatorState',
theme: ThemeData(primarySwatch: Colors.yellow),
home: MyFormPage(),
);
}
}
class MyFormPage extends StatefulWidget {
@override
_MyFormPageState createState() => _MyFormPageState();
}
class _MyFormPageState extends State<MyFormPage> {
final _formKey = GlobalKey<FormState>();
double _price;
void _save() {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
Scaffold.of(_formKey.currentContext)
.showSnackBar(SnackBar(content: Text('New price defined! ($_price)')));
}
}
Widget _buildForm(BuildContext context) {
return Container(
padding: EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TextFormField(
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter(RegExp("[0-9.]"))
],
decoration: InputDecoration(labelText: 'Price'),
keyboardType: TextInputType.numberWithOptions(decimal: true),
validator: (String value) {
double _parsedValue = double.tryParse(value);
if (_parsedValue == null) {
return "Please input a valid number";
}
if (_parsedValue == 0.0) {
return "Please input a valid price";
}
},
onSaved: (String value) {
setState(() {
_price = double.tryParse(value);
});
},
),
Text(""),
RaisedButton(
child: Text("Save"),
color: Theme.of(context).primaryColor,
textColor: Theme.of(context).primaryTextTheme.title.color,
onPressed: _save,
),
Text(""),
TextFormField(
decoration: InputDecoration(labelText: 'Copy and Paste area'),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Validator State"),
),
body: Form(
key:_formKey,
child: _buildForm(context),
),
);
}
}
但是,这与您描述的不完全相同。您要自动将,
替换为.
。我会避免这样做,因为1,234.56
会转换为1.234.56
,这是无效的。如果仅去除逗号,则最后得到有效的1234.56
。
如果您确实想按照您所说的去做,则必须使用TextEditingController
和一个函数来规范文本数据。我已经完成了以下示例,请检查一下-特别是_priceController
和_parsePrice
。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'ValidatorState',
theme: ThemeData(primarySwatch: Colors.yellow),
home: MyFormPage(),
);
}
}
class MyFormPage extends StatefulWidget {
@override
_MyFormPageState createState() => _MyFormPageState();
}
class _MyFormPageState extends State<MyFormPage> {
final _formKey = GlobalKey<FormState>();
TextEditingController _priceController;
double _price;
@override
void initState() {
super.initState();
_priceController = TextEditingController();
}
@override
void dispose() {
_priceController?.dispose();
super.dispose();
}
void _save() {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
Scaffold.of(_formKey.currentContext)
.showSnackBar(SnackBar(content: Text('New price defined! ($_price)')));
}
}
double _parsePrice(String text) {
var buffer = new StringBuffer();
text.runes.forEach((int rune) {
// acceptable runes are . or 0123456789
if (rune == 46 || (rune >= 48 && rune <= 57)) buffer.writeCharCode(rune);
// if we find a , we replace with a .
if (rune == 44) buffer.writeCharCode(46);
});
return double.tryParse(buffer.toString());
}
Widget _buildForm(BuildContext context) {
return Container(
padding: EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TextFormField(
controller: _priceController,
decoration: InputDecoration(labelText: 'Price'),
keyboardType: TextInputType.numberWithOptions(decimal: true),
validator: (String value) {
double _parsedValue = _parsePrice(value);
if (_parsedValue == null) {
return "Please input a valid number";
}
if (_parsedValue == 0.0) {
return "Please input a valid price";
}
},
onSaved: (String value) {
setState(() {
_price = _parsePrice(value);
_priceController.text = _price.toString();
});
},
),
Text(""),
RaisedButton(
child: Text("Save"),
color: Theme.of(context).primaryColor,
textColor: Theme.of(context).primaryTextTheme.title.color,
onPressed: _save,
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Validator State"),
),
body: Form(
key:_formKey,
child: _buildForm(context),
),
);
}
}
答案 2 :(得分:0)
您是否已解决此问题?
我会重新考虑您针对此问题的策略。
也许您需要的是一个观察者功能,当用户键入内容时触发该观察者功能,该功能然后查看逗号并将其更改为点。
TextFormField具有内置函数,
open Template ;;
和onEditingCompleted
可以运行您在运行验证之前必须进行检查的功能。