我有一个表单(一堆TextField小部件),我从REST API获取数据,然后使用ViewModelProvider将其加载到视图中。 现在,我想按下按钮“保存”,获取TextField小部件的文本值,然后将数据传递给REST API。
我搜索了如何获取TextField的值以在其他地方使用它,发现的所有内容都与此类似:
class _MyCustomFormState extends State<MyCustomForm> {
// Create a TextEditingController as a variable
final myController = TextEditingController();
@override
void dispose() {
myController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Retrieve Text Input'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
// Set the created TextEditingController as the controller of the Text Field
controller: myController,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
// Use the text attribute of the TextEditingController variable
content: Text(myController.text),
);
},
);
},
tooltip: 'Show me the value!',
child: Icon(Icons.text_fields),
),
);
}
}
(此代码段摘自Flutter website)
我的问题是我使用ViewModelProvider,并且需要在内部创建TextEditingController ViewModelProvider的builder属性,用于设置从HTTP调用获取的文本。
这是我当前的代码,我只留下了一个TextField,因为它们实际上是相同的。
class SettingsView extends StatelessWidget {
const SettingsView({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ViewModelProvider<SettingsViewModel>.withConsumer(
viewModel: SettingsViewModel(),
onModelReady: (model) => model.getSettings(),
builder: (context, model, child) => Center(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
TextField(
decoration: new InputDecoration(
labelText: 'Host',
),
controller: TextEditingController.fromValue(
TextEditingValue(
text: model.settings == null? '' :model.settings.host,
),
),
),
GestureDetector(
child: CallToAction("Save"),
onTap: saveData,
),
],
),
),
),
);
}
void saveData() {
}
}
问题是,如何将TextField的文本值传递给saveData方法?
谢谢。
答案 0 :(得分:0)
您是否要初始化TextEditingController?
如果是这样,则可以在onModelReady上初始化控件的文本,并在build外部声明控件。
class _SettingsViewState extends State<SettingsView> {
TextEditingController myController = TextEditingController();
@override
Widget build(BuildContext context) {
return ViewModelProvider<SettingsViewModel>.withConsumer(
viewModel: SettingsViewModel(),
onModelReady: (model) {
myController.text =
model.settings == null ? '' : model.settings.host;
model.getSettings();
},
builder: (context, model, child) => Center(
child: Column(
children: <Widget>[
Expanded(
child: TextField(
decoration: new InputDecoration(labelText: 'Host'),
controller: myController,
),
),
Expanded(
child: GestureDetector(
child: CallToAction("Save"),
onTap: saveData,
),
),
],
),
),
);
}
void saveData() {
print('save data ${myController.text}');
}
}
答案 1 :(得分:0)
感谢Thiago Dong Chen,我设法找到了解决我问题的方法。
Thiago建议我创建一个TextEditingController
变量,并在onModelReady
中设置其文本值,如下所示
onModelReady: (model) {
myController.text = model.settings == null ? '' : model.settings.host;
model.getSettings();
},
问题甚至出现在onModelReady
中,model.settings
仍然是null
。但是他的解决方案使我走上了正确的道路。我是Flutter,Dart和匿名函数的新手。看到我可以将=>
更改为更经典的{}
,使我意识到我可以在builder
中做同样的事情,而不仅仅是设置窗口小部件树。
这是完整的代码:
class SettingsView extends StatefulWidget {
const SettingsView({Key key}) : super(key: key);
@override
_SettingsViewState createState() => _SettingsViewState();
}
class _SettingsViewState extends State<SettingsView> {
TextEditingController _hostController = TextEditingController();
@override
Widget build(BuildContext context) {
return ViewModelProvider<SettingsViewModel>.withConsumer(
viewModel: SettingsViewModel(),
onModelReady: (model) => model.getSettings(),
builder: (context, model, child) {
_hostController.text = model.settings == null ? null : model.settings.host;
return Center(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
TextField(
decoration: new InputDecoration(
labelText: "Host",
),
controller: _hostController,
inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],
),
SizedBox(
height: 30,
),
GestureDetector(
child: CallToAction("Save"),
onTap: saveData,
)
],
),
),
);
}
);
}
void saveData() async{
var _api = locator<Api>();
bool b = await _api.setSettings(SettingItemModel(
host: _hostController.text));
String message = '';
if (b) {
message = 'Data saved to the database!';
} else {
message = 'Couldn\'t save the data';
}
final snackBar = SnackBar(content: Text(message));
Scaffold.of(context).showSnackBar(snackBar);
}
}