我有以下小部件,其中每个小部件都存在于各自的文件中。
(每个文件中还有很多其他事情。我对其进行了压缩,以使其最小化,以便仅查看此查询所需的内容。)
我希望在一个窗口小部件中捕获传递到TextFormField中的值,并在另一个窗口小部件中打印出这些值。
没有可视状态的变化,因此尝试不通过Provider存储这些值,我认为对于此用例来说这很愚蠢。
因此,查询是关于如何向下传递每个小部件实例在TextEditingController中捕获的值并将其向下传递给另一个小部件?
重申以下三个类,它们存在于自己的Dart文件中。
最初,我对这3种产品都坚持使用无状态小部件,但从我的阅读中可以得知,建议用户使用涉及TextEditingController的有状态小部件。
因此MyField小部件是有状态的。
MyField窗口小部件-这是根据输入的内容将值存储到控制器的地方。
class MyField extends StatefulWidget {
final String title;
final TextEditingController controller;
const MyField({this.controller, this.title});
@override
_MyFieldState createState() => _MyFieldState();
}
class _MyFieldState extends State<MyField> {
@override
Widget build(BuildContext context) {
return TextFormField(
controller: widget.controller,
);
}
}
MyForm窗口小部件-它接受上述窗口小部件的2个实例,每个实例都有其自己的控制器。
此小部件有助于将文本值向下传递到MyButton小部件。
class MyForm extends StatelessWidget {
final formKey = GlobalKey<FormState>();
final nameController = TextEditingController();
final passController = TextEditingController();
@override
Widget build(BuildContext context) {
return Form(
key: formKey,
child: Stack(
children: [
MyField(
title: 'name',
controller: nameController,
),
MyField(
title: 'pass',
controller: passController,
),
MyButton(
name: nameController.text,
pass: passController.text,
formKey: formKey)
],
),
);
}
}
MyButton窗口小部件-此窗口小部件捕获这些文本值并尝试打印出这些值,并且当前显示为空。
class MyButton extends StatelessWidget {
final formKey;
final String name;
final String pass;
const MyButton({Key key, this.formKey, this.name, this.pass}) : super(key: key);
@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: () {
// I want to be able to retrieve the text via the controllers for the 2 text fields.
// currently these values are empty which is the issue.
print('name: $name pass: $pass');
},
);
}
}
答案 0 :(得分:0)
这是我的尝试。
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _buildBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _buildBody() {
return MyForm();
}
}
class MyButton extends StatelessWidget {
final formKey;
final String label;
const MyButton({Key key, this.formKey, this.label}) : super(key: key);
@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: () {
// I want to be able to retrieve the text via the controllers for the 2 text fields.
// currently these values are empty which is the issue.
print(
'name: ${formKey.currentWidget.child.children[0].controller.text} ');
print(
'pass: ${formKey.currentWidget.child.children[1].controller.text} ');
},
child: Text(label),
);
}
}
class MyForm extends StatelessWidget {
final formKey = GlobalKey<FormState>();
final nameController = TextEditingController();
final passController = TextEditingController();
@override
Widget build(BuildContext context) {
return Form(
key: formKey,
child: Column(
children: [
MyField(
title: 'name',
controller: nameController,
),
MyField(
title: 'pass',
controller: passController,
),
MyButton(label: 'Button', formKey: formKey)
],
),
);
}
}
class MyField extends StatefulWidget {
final String title;
final TextEditingController controller;
const MyField({this.controller, this.title});
@override
_MyFieldState createState() => _MyFieldState();
}
class _MyFieldState extends State<MyField> {
@override
Widget build(BuildContext context) {
return TextFormField(
controller: widget.controller,
);
}
}
答案 1 :(得分:0)
好吧,如果您不使用用户输入的文本来更新MyButton
小部件的UI状态,您甚至不需要它,您只需访问MyForm
小部件中的控制器文本即可。
class MyForm extends StatelessWidget {
final formKey = GlobalKey<FormState>();
final nameController = TextEditingController();
final passController = TextEditingController();
@override
Widget build(BuildContext context) {
return Form(
key: formKey,
child: Column(
children: [
MyField(
title: 'name',
controller: nameController,
),
MyField(
title: 'pass',
controller: passController,
),
RaisedButton(
onPressed() {
print("${nameController.text}");
print("${passController.text}");
}
),
],
),
);
}
}
但是,如果您想在用户键入文本时动态更新MyButton
小部件,则MyForm
小部件必须为Statefull
,并且必须在每个用户类型事件中进行重建。 / p>
//NOTE: Assuming `MyForm` is a Statefull widget
final nameController = TextEditingController();
final passController = TextEditingController();
@override
void initState() {
// listening the textfield.
nameController.addListener(_controllerListener);
passController.addListener(_controllerListener);
super.initState();
}
void _controllerListener(){
if(mounted)
setState((){});
}
@override
Widget build(BuildContext context) {
return Form(
key: formKey,
child: Stack(
children: [
MyField(
title: 'name',
controller: nameController,
),
MyField(
title: 'pass',
controller: passController,
),
MyButton(
name: nameController.text,
pass: passController.text,
onPressed: () {
print("${nameController.text} - ${passController.text}");
})
],
),
);
}
}
class MyButton extends StatelessWidget {
final String name;
final String pass;
final VoidCallback onPressed;
const MyButton({Key key, this.onPressed, this.name, this.pass}) : super(key: key);
@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: this.onPressed,
// updating UI on type event.
child: Text('$name and $pass'),
);
}
}
答案 2 :(得分:0)
请将MyForm
类更改为以下类...
这个怎么运作 ?
在TextFormField上进行每次更改后,您的Button应该重新构建,因此我使用了Stream构建器和Stream
class MyForm extends StatelessWidget {
final formKey = GlobalKey<FormState>();
final nameController = TextEditingController();
final passController = TextEditingController();
StreamController<int> sc = StreamController<int>();
@override
Widget build(BuildContext context) {
return Form(
key: formKey,
onChanged: () {
sc.add(1);
},
child: Column(
children: [
MyField(
title: 'name',
controller: nameController,
),
MyField(
title: 'pass',
controller: passController,
),
StreamBuilder<int>(
stream: sc.stream,
builder: (context, snapshot) {
return MyButton(
name: nameController.text,
pass: passController.text,
formKey: formKey);
}
)
],
),
);
}
}
答案 3 :(得分:0)
您可以将值存储在目标文件中,并从项目中的任何其他文件中获取或编辑其值。例如,在名为user.dart的文件中:
ID | column 1 | column 2
1 | peter | blue
2 | mark | red
1 | peter | blue
然后在其他任何位置导入文件并根据需要设置或获取其值:
class user {
static String name;
static String pass;
}
如果您的问题是您想在单击按钮之前显示文本,那么我认为您可以使小部件成为有状态的,然后可以在“文本”字段中使用change事件:
user.name = nameController.text
user.pass = passController.text
print('name: ' + user.name + 'pass: ' + user.pass);