I have a Flutter App with Provider as a State Manager. The ChangeNotifierProvier is at the very top of my app (ie. above MaterialApp widget).
I have a ChangeNotifier class as follows:
class AmountManager extends ChangeNotifier {
String amount;
void changeAmount(String newAmount) {
amount = newAmount;
notifyListeners();
}
}
Then I have another class with a TextField :
class MyTextField extends StatelessWidget {
#override
Widget build(BuildContext context) {
return TextField(
//some decorations here
onChanged(value) {
Provider.of<AmountManager>(context).changeAmount(value);
},
);
}
}
And in another class under the Main App, I call the amount variable:
class MyText extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text(
Provider.of<AmountManager>(context).amount,
);
}
}
The problem is the Provider.of(...) method cannot be called. I watched some tutorials and couldn't find out the reason behind it. If I use static text instead of the AmountManager object, it works. The program only uses the initial value of amount in MyText class.
What do you think I'm wrong with?
Thank you in advance,
You need listen: false when you use Provider.of() in onChanged.
onChanged: (value) {
Provider.of<AmountManager>(context, listen: false).changeAmount(value);
},
See this for details.
Related
I'm trying to change the variable from another stateful class.
class first extends statefulwidget {
bool text = false;
Widget build(BuildContext context) {
setState((){});
return Container(
child: text ? Text('Hello') : Text('check')
);
}
}
class second extends statefulwidget {
Widget build(BuildContext context) {
return Container(
child: IconButton(
onPressed: () {
first fir = first();
setState((){
fir.test = true;
});
}
)
);
}
}
widget shows only check not showing Hello
This is my code...Ignore spelling mistakes and camelcase
Give me the solutions if you know..
If you are trying to access data on multiple screens, the Provider package could help you. It stores global data accessible from all classes, without the need of creating constructors. It's good for big apps.
Here are some steps to use it (there is also a lot of info online):
Import provider in pubspec.yaml
Create your provider.dart file. For example:
class HeroInfo with ChangeNotifier{
String _hero = 'Ironman'
get hero {
return _hero;
}
set hero (String heroName) {
_hero = heroName;
notifyListeners();
}
}
Wrap your MaterialApp (probably on main.dart) with ChangeNotifierProvider.
return ChangeNotifierProvider(
builder: (context) => HeroInfo(),
child: MaterialApp(...),
);
Use it on your application! Call the provider inside any build method and get data:
#override
Widget build(BuildContext context){
final heroProvider = Provider.of<HeroInfo>(context);
return Column {
children: [
Text(heroProvider.hero)
]
}
}
Or set data:
heroProvider.hero = 'Superman';
try to reference to this answer, create function to set boolean in class1 and pass as parameter to class 2 and execute it :
typedef void MyCallback(int foo);
class MyClass {
void doSomething(int i){
}
MyOtherClass myOtherClass = new MyOtherClass(doSomething);
}
class MyOtherClass {
final MyCallback callback;
MyOtherClass(this.callback);
}
I am using Flutter getx package.
I know how to use "ever" with (.obs) variable like this
class CountController extends GetxController {
final count = 0.obs;
#override
void onInit() {
ever(count1, (_) => print("$_ has been changed"));
super.onInit();
}
}
But how to use "ever()" or triggering specific callbacks when variable change if the variable doesn't have (.obs) because I am using GetBuilder (not : Obx or GetX) in my view
class AnyScreen extends StatelessWidget {
final controller = Get.put(CounterController());
#override
Widget build(BuildContext context) {
ever(controller.counter, (value) => print("$value has been changed"));
}
#override
Widget build(BuildContext context) {
return Text("whatever!");
}
}
NOTE: Workers should always be used when starting a Controller or Class, so it should always be on onInit (recommended), Class constructor, or the initState of a StatefulWidget (this practice is not recommended in most cases, but it shouldn't have any side effects)
docs
How do I access the variable "selectedTag" from this statefulWidget:
class _AlertDialogOneState extends State<AlertDialogOne> {
Item selectedTag;
...
}
}
inside this statelessWidget :
class CardTile extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(...
Pass it as parameter,
class CardTile extends StatelessWidget {
final Item selectedTag;// Add this
CardTile(this.selectedTag); // Add this
#override
Widget build(BuildContext context) {
return Container(...
To pass this variable, you have multiple ways:
Pass it as a constructor when u navigate to this class using your navigator
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CardTile(selectedTag)),
);
class CardTile extends StatelessWidget {
Item selectedTag;
CardTile(this.selectedTag);
#override
Widget build(BuildContext context) {
return Container(...
Use a state management like provider
class ProviderData with ChangeNotifier {
Item selected;
void changeSelection(newSelect) {
selected = newSelect;
changeNotifier();
}
}
and inside any class you need call this:
final providerData = Provider.of<ProviderData>(context);
so you can access the variable or change it using this instance like this:
final variable = providerData.selected;
providerData.changeSelection(newValue);
print(variable);
hope this help but i see that it is better to pass it through the constructor if you are not using a state managemnt, however i just gave you an example for illustration
I am an entry level flutter developer and I've been stuck for a while on this problem, I've tried different things
I am try to make the 'Note Title' (that particular widget), pop out
The app_issue description
then this should show instead
desired result
The two different content under the "My Notes" tab are two Stateful Widgets and the "My Notes" tab is another Stateful Widget on its own
I've tried using a function but it doesn't work
enum MyNoteContent {
staticNote,
dynamicNote,
}
MyNoteContent selectedContent = MyNoteContent.staticNote;
Widget updateMyNotes() {
if (selectedContent == MyNoteContent.staticNote) {
return MyNoteStatic();
} else {
return MyNoteDynamic();
}
}
and then i call the function in the MyNotes Widget
class _MyNotesTabState extends State<MyNotesTab> {
#override
Widget build(BuildContext context) {
return updateMyNotes();
}
}
I trying to update the value in the first content that is shown (in its own Widget), so that when it is pressed, it should change
class _MyNoteStaticState extends State<MyNoteStatic> {
#override
Widget build(BuildContext context) {
return Container(
child: RawMaterialButton(
onPressed: () {
setState(() {
selectedContent = MyNoteContent.dynamicNote;
updateMyNotes();
});
},
but it does not work
Code to Reproduce the Problem
The issue here is that the setState you're calling is for the _MyNoteStaticState class. This means it will only rebuild the MyNoteStatic widget. But in order for the page to change you need to rebuild its parent _MyNotesTabState. So you need to call the setState method of _MyNotesTabState which can be done by passing a callback down from _MyNotesTabState to _MyNoteStaticState.
First, move updateMyNotes & selectedContent into the _MyNotesTabState class since that's the only place they're needed.
Make a new function that rebuilds _MyNotesTabState and changes selectedContent in _MyNotesTabState.
void changeNote() {
setState(() {
selectedContent = MyNoteContent.dynamicNote;
});
}
Pass it down to MyNoteStatic
Widget updateMyNotes() {
if (selectedContent == MyNoteContent.staticNote) {
return MyNoteStatic(changeNote);
} else {
return MyNoteDynamic();
}
}
and modify MyNoteStatic to accept this callback as a parameter
class MyNoteStatic extends StatefulWidget {
final VoidCallback callback;
MyNoteStatic(this.callback);
#override
_MyNoteStaticState createState() => _MyNoteStaticState();
}
Then pass this callback to your button instead of what you currently have:
child: RawMaterialButton(
onPressed: widget.callback,
)
Full relevant code incorporating the above changes:
enum MyNoteContent {
staticNote,
dynamicNote,
}
class MyNotesTab extends StatefulWidget {
#override
_MyNotesTabState createState() => _MyNotesTabState();
}
class _MyNotesTabState extends State<MyNotesTab> {
MyNoteContent selectedContent = MyNoteContent.staticNote;
#override
Widget build(BuildContext context) {
return updateMyNotes();
}
Widget updateMyNotes() {
if (selectedContent == MyNoteContent.staticNote) {
return MyNoteStatic(changeNote);
} else {
return MyNoteDynamic();
}
}
void changeNote() {
setState(() {
selectedContent = MyNoteContent.dynamicNote;
});
}
}
//Static Note
class MyNoteStatic extends StatefulWidget {
final VoidCallback callback;
MyNoteStatic(this.callback);
#override
_MyNoteStaticState createState() => _MyNoteStaticState();
}
class _MyNoteStaticState extends State<MyNoteStatic> {
#override
Widget build(BuildContext context) {
return Container(
child: RawMaterialButton(
onPressed: widget.callback,
...
i want to know how to pass data from one class to another class.
Main CLASS
void WhenPageScroll() {
int USERID = int.parse(complexTutorial.data[_pageController.page.toInt()].userId);
print("ID $USERID");
Tut(int.parse(complexTutorial.data[_pageController.page.toInt()].userId));
}
Tut Class
class Tut extends StatefulWidget {
Tut(this.USERID);
final int USERID;
#override
_TutState createState() => _TutState();
}
class _TutState extends State<Tut>{
#override
Widget build(BuildContext context) {
return Container(child: LoadTut(),);
}
LoadTut(){
return Center(child: Text("CENTER TEXT WITH " + widget.USERID.toString()));
}
}
i am using this method but no working how can i do that on page Scrolled?
Note : when i am using setState then whole page are reload but i want to reload only Tut on Scrolled.
Thanks Team.