Provider does not update Text widget - flutter

I have a problem with updating text widget in Level3 class after input some text in textField widget.
Appreciate your help
Expose data in below code:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
// home: TasksScreen(),
home: ChangeNotifierProvider<Data>(
create: (context) => Data(),
child: Scaffold(
appBar: AppBar(
title: Container(
child: MyText(),
),
),
body: Level1(),
),
),
);
}
}
create Data class for model data in below class
class Data extends ChangeNotifier {
String data = 'this data';
void changeString(String newString) {
data = newString;
print(newString);//don't print anything after typing in textFild
print(data);//don't print either
notifyListeners();
}
}
I want to use Data object properties in MyTextField in below code
but it seems do not trigger Provider.of<Data>(context).changeString(newValue)
class MyTextField extends StatelessWidget {
#override
Widget build(BuildContext context) {
return TextField(
onChanged: (newValue) {
print(newValue);//print newValue correctly
Provider.of<Data>(context).changeString(newValue);
},
);
}
}
class Level3 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text(
//this part don't update as typing in textField
Provider.of<Data>(context).data,
//will return an instance of Provider
//type found in the context that is sent as a parameter
),
),
);
}
}

You can copy paste run full code below
In onChanged, You can use listen: false
code snippet
return TextField(
onChanged: (newValue) {
print(newValue); //print newValue correctly
Provider.of<Data>(context, listen: false).changeString(newValue);
},
);
working demo
full code
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Data extends ChangeNotifier {
String data = 'this data';
void changeString(String newString) {
data = newString;
print(newString); //don't print anything after typing in textFild
print(data); //don't print either
notifyListeners();
}
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
// home: TasksScreen(),
home: ChangeNotifierProvider<Data>(
create: (context) => Data(),
child: Scaffold(
appBar: AppBar(
title: Container(
child: MyTextField(),
),
),
body: Level3(),
),
),
);
}
}
class MyTextField extends StatelessWidget {
#override
Widget build(BuildContext context) {
return TextField(
onChanged: (newValue) {
print(newValue); //print newValue correctly
Provider.of<Data>(context, listen: false).changeString(newValue);
},
);
}
}
class Level3 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text(
//this part don't update as typing in textField
Provider.of<Data>(context).data,
//will return an instance of Provider
//type found in the context that is sent as a parameter
),
),
);
}
}
void main() {
runApp(MyApp());
}

You can try this
(context.watch<Data>().data).toString();

Related

How to change the text color which is in a different widget on switch with a flutter provider?

How to change the text color which is in a different widget on switch with a flutter provider?
When switch is on change text color to red else change to green. Bu don't merge first and second widgets.
When clicked switch button change other widget's text.
`
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(const SwitchApp());
class SwitchApp extends StatelessWidget {
const SwitchApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Switch Sample')),
body: const Center(
child: SwitchExample(),
),
),
);
}
}
class SwitchExample extends StatefulWidget {
const SwitchExample({super.key});
#override
State<SwitchExample> createState() => _SwitchExampleState();
}
class _SwitchExampleState extends State<SwitchExample> {
bool light = false;
#override
Widget build(BuildContext context) {
return Column(
children: [
Switch(
// This bool value toggles the switch.
value: light,
activeColor: Colors.red,
onChanged: (bool value) {
// This is called when the user toggles the switch.
setState(() {
light = value;
});
},
),
MyText()
],
);
}
}
class MyText extends StatelessWidget {
const MyText({super.key});
#override
Widget build(BuildContext context) {
return const Text('Change my color',
style: TextStyle(color: Colors.green));
}
}
`
The easiest way would be to pass the color down into the constructor of MyText widget, since MyText widget is being built as a child of SwitchExample which is handling the switch state.
import 'package:provider/provider.dart';
void main() => runApp(const SwitchApp());
class SwitchApp extends StatelessWidget {
const SwitchApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Switch Sample')),
body: const Center(
child: SwitchExample(),
),
),
);
}
}
class SwitchExample extends StatefulWidget {
const SwitchExample({super.key});
#override
State<SwitchExample> createState() => _SwitchExampleState();
}
class _SwitchExampleState extends State<SwitchExample> {
bool light = false;
#override
Widget build(BuildContext context) {
return Column(
children: [
Switch(
// This bool value toggles the switch.
value: light,
activeColor: Colors.red,
onChanged: (bool value) {
// This is called when the user toggles the switch.
setState(() {
light = value;
});
},
),
MyText(light ? Colors.green : Colors.blue)
],
);
}
}
class MyText extends StatelessWidget {
final Color color;
const MyText(this.color, {super.key});
#override
Widget build(BuildContext context) {
return Text('Change my color',
style: TextStyle(color: color));
}
}
But, if you wanted to use provider so that MyText could be a child widget anywhere below the provider widget in the tree you could use Provider with a ChangeNotifier:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(const SwitchApp());
class ColorModel extends ChangeNotifier {
Color color = Colors.green;
void setColor(Color color) {
this.color = color;
notifyListeners();
}
}
class SwitchApp extends StatelessWidget {
const SwitchApp({super.key});
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<ColorModel>(
create: (context) => ColorModel(),
child: MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Switch Sample')),
body: const Center(
child: SwitchExample(),
),
),
),
);
}
}
class SwitchExample extends StatefulWidget {
const SwitchExample({super.key});
#override
State<SwitchExample> createState() => _SwitchExampleState();
}
class _SwitchExampleState extends State<SwitchExample> {
bool light = false;
#override
Widget build(BuildContext context) {
return Column(
children: [
Switch(
// This bool value toggles the switch.
value: light,
activeColor: Colors.red,
onChanged: (bool value) {
// This is called when the user toggles the switch.
setState(() {
light = value;
});
Provider.of<ColorModel>(context, listen: false)
.setColor(value ? Colors.green : Colors.blue);
},
),
MyText()
],
);
}
}
class MyText extends StatelessWidget {
const MyText({super.key});
#override
Widget build(BuildContext context) {
return Consumer<ColorModel>(builder: (context, state, _) {
return Text('Change my color', style: TextStyle(color: state.color));
});
}
}
Check out flutter's docs for more info: https://docs.flutter.dev/development/data-and-backend/state-mgmt/simple

Flutter Retrieve Value from TextField

I'm trying to get the value from the TextField then compare it to a string = '123'
If the value = '123' then alert 'Successful!' or else alert 'Failed!'
Here is my code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Retrieve Text Input',
home: MyCustomForm(),
);
}
}
class MyCustomForm extends StatefulWidget {
#override
_MyCustomFormState createState() => _MyCustomFormState();
}
class _MyCustomFormState extends State<MyCustomForm> {
TextEditingController myController = new TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Retrieve Text Input'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
controller: myController,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
if(myController == '123')
{
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text('Successful!'),
);
},
);
}
else
{
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text('Failed!'),
);
},
);
}
},
child: Icon(Icons.text_fields),
),
);
}
}
My code always shows failed even I entered '123'. Can someone help me to figure out what I did wrong here? Thank you
To access the text inside a TextField Controller, you need to use myController.text, the myController is just a controller itself so you can't compare it to a String like that.
So, you should change this line
if(myController == '123')
into this
if(myController.text == '123')

I am using notifyListner from flutter Provider package but my UI is not updating

I am using notifyListner from flutter Provider package but my UI is not updating whenever I am typing the letters in the TextField. I am making this app just to understand how Provider works. My appbar and text is supposed to change whenever I type the text in TextFiled. Here's my code,
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<Data>(
create: (context) => Data(),
child: MaterialApp(
home: Scaffold(
appBar: AppBar(
title: MyAppBar(),
),
body: SafeArea(
child: Column(
children: [
MyTextField(),
Expanded(
child: MyTextWidget(),
),
],
),
),
),
),
);
}
}
class MyTextField extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: TextField(
onChanged: (newValue) {
Provider.of<Data>(context, listen: true).changeString(newValue);
},
),
);
}
}
class MyTextWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Text(Provider.of<Data>(context, listen: true).appName),
);
}
}
class MyAppBar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text(Provider.of<Data>(context, listen: true).appName);
}
}
class Data extends ChangeNotifier {
String appName = 'Understanding Provider';
void changeString(String newString) {
appName = newString;
notifyListeners();
}
}
Please somebody help, Thanks!
You should not listen to your provider when you update it inside MyTextField:
class MyTextField extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: TextField(
onChanged: (newValue) {
Provider.of<Data>(context, listen: false).changeString(newValue);
},
),
);
}
}
Set listen: false.

I am trying provider, it seams everything fine, but the textField text is not updating in my text widget

I am practicing the state management. I am trying to update my textField (First class) to the TextWidgetwhich was in the Second() class. I don't know what problem i have made here?
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<Data>(
create: (context) => Data(),
child: MaterialApp(
home: First(),
),
);
}
}
My First Class
class First extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
TextField(
onChanged: (value) {
Provider.of<Data>(context).changeString(value);
},
),
Second(),
],
}
The Second Class
class Second extends StatelessWidget {
#override
Widget build(BuildContext context) {
return
Text(
Provider.of<Data>(context).text,
);
}
}
My Data class which extends ChangeNotifier
class Data extends ChangeNotifier {
String text = 'Type Something';
void changeString(String newText) {
text = newText;
notifyListeners();
}
}
Add a consumer to rebuild your widget with the new data.
Consumer<Data>(
builder: (context, value, _) => Text(
Provider.of<Data>(context).text,
);

Why can't I get the provider package to listen to a change?

So I'm writing a very simple app, just to learn a little bit more about the provider package in flutter. The app is this:
App functionallity
When I write in mi TextField, the text bellow it should change and the title should remain unchanged, but I can't get it to listen the changes from changeText method. The code is
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<Data>(
create: (context) => Data(),
child: MaterialApp(
home: Scaffold(
appBar: AppBar(
title: MyText(),
),
body: Container(
child: Level1(),
),
),
),
);
}
}
class Level1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Level2(),
);
}
}
class Level2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
MyTextField(),
Level3(),
],
),
);
}
}
class Level3 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text(Provider.of<Data>(context, listen: false).data);
}
}
class MyText extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text(context.watch<Data>().data);
}
}
class MyTextField extends StatelessWidget {
#override
Widget build(BuildContext context) {
return TextField(
onChanged: (newText) {
Provider.of<Data>(context).changeText(newText);
print(newText);
},
);
}
}
class Data extends ChangeNotifier {
String data = 'Hello';
void changeText(String newString) {
data = newString;
print('Hello $data');
notifyListeners();
}
}
Try putting the TextField widget inside a Stateful widget.
return TextField(
onChanged: (newText) {
Provider.of<Data>(context).changeText(newText);
print(newText);
},
);
Enclose this in a stateful widget
Also you have to add a Text controller to the textfield widget, go to docs for textfield widget in flutter.