Adding data to a list on another page Flutter - flutter

I have a list of event name in a stateful widget like this
main.dart
class Fav extends StatefulWidget {
#override
_FavState createState() => _FavState();
}
class _FavState extends State<Fav> {
final PageController ctrl = PageController(viewportFraction: 0.8);
final Firestore db = Firestore.instance;
Stream slides;
var fav = ['3-Tech Event'];
.
.
.
And on another page, I want to add a string, let's say,
'5-Art Exhibit'
into the
var fav = ['3-Tech Event'];
to get the final result
fav = ['3-Tech Event', '5-Art Exhibit'];
on the page above. How do I do that? Here's my code for the button
Event.dart
class Star extends StatefulWidget {
#override
_StarState createState() => _StarState();
}
class _StarState extends State<Star> {
Color _iconColor = Colors.grey;
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(55.0),
child: Transform.scale(
scale: 2.0,
child: IconButton(
icon: Icon(
Icons.star,
color: _iconColor,
),
onPressed: () {
setState(() {
_iconColor = (_iconColor == Colors.yellow) ? Colors.grey : Colors.yellow;
});
})
),
);
}
}
Thank you in advance!
UPDATE
I followed #Viren V Varasadiya advice and updated my code to this
main.dart
class Fav extends StatefulWidget {
#override
_FavState createState() => _FavState();
}
class _FavState extends State<Fav> {
var fav = ['3-Tech Event'];
updatedata(String item) {
setState(() {
fav.add(item);
});
}
And on the other file, I removed Star class (because it's intended to be used in another class anyway) and it looked like this
class Event extends StatefulWidget {
final eventInfo;
Event({Key key, List eventInfo}) //I have to pass a list of data to this
: this.eventInfo = eventInfo, //page from another class
super(key: key);
final Function updatedata;
Event.addToFavWith({this.updatedata});
#override
_EventState createState() => _EventState();
}
class _EventState extends State<Event> {
Color _iconColor = Colors.grey;
#override
Widget build(BuildContext context) {
.
.
.
Container( //This used to be Container(child:Star())
child: InkWell(
child: Container(
padding: EdgeInsets.all(55.0),
child: Transform.scale(
scale: 2.0,
child: IconButton(
icon: Icon(
Icons.star,
color: _iconColor,
),
onPressed: () {
setState(() {
_iconColor = (_iconColor == Colors.yellow)
? Colors.grey
: Colors.yellow;
widget.updatedata(name);
});
})),
),
)),
And now I get a couple of errors.
All final variables must be initialized, but 'eventInfo' is not. Try
adding an initializer for the field.
All final variables must be initialized, but 'updatedata' is not. Try
adding an initializer for the field.

You have to create a function in parent widget and pass it to child widget and call it in child widget, we work for you.
Following minimal code help you more.
class DeleteWidget extends StatefulWidget {
#override
_DeleteWidgetState createState() => _DeleteWidgetState();
}
class _DeleteWidgetState extends State<DeleteWidget> {
var fav = ['3-Tech Event'];
updatedata(String item) {
setState(() {
fav.add(item);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(fav.toString()),
Star(
updatedata: updatedata,
),
],
)));
}
}
class Star extends StatefulWidget {
final Function updatedata;
Star({this.updatedata});
#override
_StarState createState() => _StarState();
}
class _StarState extends State<Star> {
#override
Widget build(BuildContext context) {
return Container(
child: RaisedButton(
child: Text("add item"),
onPressed: () {
widget.updatedata('5-Art Exhibit');
}),
);
}
}
Update:
There is no need to create named constructor.
class Event extends StatefulWidget {
final eventInfo;
Event({Key key, List eventInfo, this.updatedata}) //I have to pass a list of data to this
: this.eventInfo = eventInfo, //page from another class
super(key: key);
final Function updatedata;
#override
_EventState createState() => _EventState();
}

Related

Flutter: Closure dynamic from Function static

I have created a function to get a random element from a list. It works perfectly in dartpad but when I put it into my Flutter app I get the following error:
Closure: (List<dynamic>) => dynamic from Function 'player1': static.
The contents of the dart file:
import 'package:flutter/material.dart';
import 'dart:math';
List<String> players = ["Alice", "Jane", "Susan"];
String tempPlayer = "";
player1(List players) {
//players[Random().nextInt(players.length)];
String tempPlayer = players[Random().nextInt(players.length)];
return tempPlayer;
}
class RandPlay extends StatefulWidget {
const RandPlay({Key? key}) : super(key: key);
#override
State<RandPlay> createState() => _RandPlayState();
}
class _RandPlayState extends State<RandPlay> {
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
ElevatedButton(
onPressed: () {
setState(() {
print(player1);
});
},
child: Text("Random")),
Text("$player1"),
],
),
);
}
}
I am new to this and I am really confused... I have tried searching for similar situations to no avail. Assistance would be greatly appreciated.
player1 is a method, expect a list.
You can do it like
List<String> players = ["Alice", "Jane", "Susan"];
String player1(players) {
String tempPlayer = players[Random().nextInt(players.length)];
return tempPlayer;
}
class RandPlay extends StatefulWidget {
const RandPlay({Key? key}) : super(key: key);
#override
State<RandPlay> createState() => _RandPlayState();
}
class _RandPlayState extends State<RandPlay> {
late String tempPlayer = player1(players);
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
ElevatedButton(
onPressed: () {
tempPlayer = player1(players);
setState(() {});
},
child: Text("Random")),
Text("$tempPlayer"),
],
),
);
}
}

flutter can't access static variable

I want to access a static variable in a stateful widget in a flutter.
but it does not work.
and someone said that is a private widget and I can't access it.
so how can I access the variable isCollapsed in the below code:
class BottomNavBar extends StatefulWidget {
final int activeTabIndex;
const BottomNavBar({Key? key, required this.activeTabIndex})
: super(key: key);
#override
_BottomNavBarState createState() => _BottomNavBarState();
}
class _BottomNavBarState extends State<BottomNavBar> {
static var isCollapsed = false;
#override
Widget build(BuildContext context) {
Scaffold(
body: SlidingUpPanel(
controller: _pc,
panelBuilder: (sc) {
if (isCollapsed == false) _pc.hide();
if (isCollapsed == true) _pc.show();
return Container(
child: Center(child: Text("Panel")),
);
},
body: Text("something");
), }
}
I want to change isCollapsed in another class,
when clicked on the icon, isCollapsed changes to true.
class _PlayerPreviewState extends State<PlayerPreview> {
#override
Widget build(BuildContext context) {
final String play = 'assets/icons/play.svg';
var pageWidth = MediaQuery.of(context).size.width;
return Padding(
padding: EdgeInsets.only(top: pageWidth * .04),
child: IconButton(
onPressed: () {
},
icon: SvgPicture.asset(play),
),
);}}
can anyone help me please how can I do it?
Yes, _BottomNavBarState is private because it starts with underscore_. if you want to make it public, remove _ from name and it will be like
#override
BottomNavBarState createState() => BottomNavBarState();
}
class BottomNavBarState extends State<BottomNavBar> {
static var isCollapsed = false;
and use anywhere like BottomNavBarState.isCollapsed, but I should prefer state-management while the variable has effects on state.
For more about
state-management
dart

Delete specific widget | Flutter & Riverpod

As shown in the image, I'm trying to have a list of dice where I can add or delete a die. I've tried StateProvider, ChangeNotifier, and StateNotifier. Each one doesn't seem to work as I expect it to. I'm trying to make a provider that contains a list of dieWidgets, but I can't figure out how to remove a specific die when I longpress on it. The image shows a popup menu to delete it, that's the long-term goal, but just a longpress delete would be good for now. Thoughts on how to approach this?
Code
main.dart
class DiceNotifier extends ChangeNotifier {
List<DieWidget> dice = [];
void add() {
dice.add(DieWidget());
notifyListeners();
}
void removeDie(int id) {
// FIXME: Unable to delete a die based on id
print(id);
notifyListeners();
}
}
final diceProvider = ChangeNotifierProvider((_) {
return DiceNotifier();
});
class MyHomePage extends ConsumerWidget {
#override
Widget build(BuildContext context, ScopedReader watch) {
final dice = watch(diceProvider).dice;
return Scaffold(
appBar: AppBar(
title: Text("Dice"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
...dice,
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.read(diceProvider).add();
},
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
die_widget.dart
class DieWidget extends StatefulWidget {
#override
_DieWidgetState createState() => _DieWidgetState();
}
class _DieWidgetState extends State<DieWidget> {
int value = 0;
int id = 0;
#override
Widget build(BuildContext context) {
return FlatButton(
child: Text(
'$value',
),
onPressed: () {
setState(() {
value++;
id++;
});
// context.read(dieProvider).increment();
},
onLongPress: () {
final dice = context.read(diceProvider);
dice.removeDie(id);
// print(this.value);
},
);
}
}
One solution would be to define a parameter value in the DiceWidget class:
class DiceWidget extends StatefulWidget {
const DiceWidget({ Key key, this.value }) : super(key: key);
int value;
#override
_DiceWidgetState createState() => _DiceWidgetState();
}
And access this data from the DiceWidget:
class DiceWidget extends StatefulWidget {
#override
_DiceWidgetState createState() => _DiceWidgetState();
}
class _DiceWidgetState extends State<DiceWidget> {
#override
Widget build(BuildContext context) {
return FlatButton(
child: Text(
widget.value.toString() ?? '',
),
onLongPress: () {
final dice = context.read(diceProvider);
dice.removeDice(widget.value);
// print(widget.value);
},
);
}
}
In the DiceNotifier class, I'd recommend to implement the dices array as a List<int>:
List<int> dices = [];
Therefore, the addDice() and removeDice() functions will be, respectively:
class DiceNotifier extends ChangeNotifier {
List<int> dices = [];
void addDice() {
dices.add(dices.length);
notifyListeners();
}
void removeDice(int id) {
dices.remove(id);
print(id);
notifyListeners();
}
}
To make the example work, we need to modify the MyHomePage Column children as well, to build the list of DiceWidgets:
...dices.map((d) => DiceWidget(value: d)).toList(),
The whole example will then be:
main.dart:
class DiceNotifier extends ChangeNotifier {
List<int> dices = [];
void addDice() {
dices.add(dices.length);
notifyListeners();
}
void removeDice(int id) {
dices.remove(id);
print(id);
notifyListeners();
}
}
final diceProvider = ChangeNotifierProvider((_) {
return DiceNotifier();
});
class MyHomePage extends ConsumerWidget {
#override
Widget build(BuildContext context, ScopedReader watch) {
final dices = watch(diceProvider).dices;
return Scaffold(
appBar: AppBar(
title: Text("Dice"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
...dices.map((d) => DiceWidget(value: d)).toList(),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.read(diceProvider).addDice();
},
child: Icon(Icons.add),
),
);
}
}
dice_widget.dart:
class DiceWidget extends StatefulWidget {
#override
_DiceWidgetState createState() => _DiceWidgetState();
}
class _DiceWidgetState extends State<DiceWidget> {
#override
Widget build(BuildContext context) {
return FlatButton(
child: Text(
widget.value.toString() ?? '',
),
onLongPress: () {
final dice = context.read(diceProvider);
dice.removeDice(widget.value);
print(widget.value);
},
);
}
}

Passing data from one widget to another

I have a list of choice widget and want to pass the selected choice to another widget.
Here is the list of choice widget
class ChoiceChipWidget extends StatefulWidget {
final List<String> reportList;
final Function(String item) onChoiceSelected;
ChoiceChipWidget(this.reportList, this.onChoiceSelected);
#override
_ChoiceChipWidgetState createState() => new _ChoiceChipWidgetState();
}
class _ChoiceChipWidgetState extends State<ChoiceChipWidget> {
String selectedChoice = "";
_buildChoiceList() {
List<Widget> choices = List();
widget.reportList.forEach((item) {
choices.add(Container(
child: ChoiceChip(
label: Text(item),
selected: selectedChoice == item,
onSelected: (selected) {
setState(() {
selectedChoice = item;
widget.onChoiceSelected(item);
print(selectedChoice); //DATA THAT NEEDS TO BE PASSED
});
},
),
));
});
return choices;
}
#override
Widget build(BuildContext context) {
return Wrap(
children: _buildChoiceList(),
);
}
}
I need to pass it to this widget
class AddCashPage extends StatefulWidget {
#override
_AddCashPageState createState() => _AddCashPageState();
}
class _AddCashPageState extends State<AddCashPage> {
void createTodo() async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
String repetition = //DATA NEEDS TO GO HERE;
final addCash = AddCash(repetition);
setState(() {
id = addCash.id;
});
}
}
#override
Widget build(BuildContext context) {
return Container(
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
ChoiceChipWidget(chipList, (item) {
selectedItem = item;
}),
],
),
RaisedButton(
child: Text("Update Cash Flow"),
onPressed: createTodo,
),
],
),
),
);
}
}
I tried making a constructor inside AddCashPage
like this
class AddCashPage extends StatefulWidget {
final ChoiceChipWidget choiceChipWidget;
AddCashPage({Key key, #required this.choiceChipWidget}) : super(key: key);
#override
_AddCashPageState createState() => _AddCashPageState();
}
I think you just missed to call setState() in here:
ChoiceChipWidget(chipList, (item) {
selectedItem = item;
}),
Like this:
ChoiceChipWidget(chipList, (item) {
setState(() => selectedItem = item);
}),
Then you could do this:
AddCash(selectedItem)
Make sure to declare the selectedItem variable inside _AddCashPageState, I don't see it on your code.
Your choice widget passes the data to the AddCashPage via the constructor you created, but you're missing something. You need to pass the data that AddCashPage has to its state (_AddCashState) so that you can use it there. Basically, you need to create one more constructor.
class AddCashPage extends StatefulWidget {
final ChoiceChipWidget choiceChipWidget;
AddCashPage({Key key, #required this.choiceChipWidget}) : super(key: key);
#override
_AddCashPageState createState() => _AddCashPageState(choiceChipWidget: choiceChipWidget);
}
And in _AddCashPageState:
class _AddCashPageState extends State<AddCashPage> {
final choiceChipWidget;
_AddCashPageState({Key key, #required this.choiceChipWidget});
}
To use your passed data inside _AddCashPageState class you can use widget property of the corresponding state of the related Stateful class.
For Ex : To use choice chip widget in your class you can use it like widget.ChoiceChipWidget
Any properties/methods provided in AddCashPage class can be accessed in its State class _AddCashPageState() using widget.ChoiceChipWidget property;
You can use this widget property inside methods only like, initState(), build(), dispose() etc.

This class is marked as '#immutable', but one or more of its instance fields are not final:

If I am declaring the variables as final then the values(variables) I want to change(on pressed) are in setState(){} so those variables can be changed What to do to prevent this?
Also, why is it written widget.value?
I have tried using static instead of final doesn't work
class BottomCard extends StatefulWidget {
String title;
int value;
#override
_BottomCardState createState() => _BottomCardState(); }
class _BottomCardState extends State<BottomCard> {.....
....<Widget>[
FloatingActionButton(
elevation: 0,
child: Icon(FontAwesomeIcons.plus),
onPressed: () {
setState(() {
widget.value++;
});
},
backgroundColor: Color(0xFF47535E),
),
If you don't need to get variables (title & value) from outside your widget, you can declare them in the _BottomCardState class and use them as you want, for example:
class BottomCardState extends StatefulWidget {
#override
_BottomCardStateState createState() => _BottomCardStateState();
}
class _BottomCardStateState extends State<BottomCardState> {
int _value;
String title;
#override
void initState() {
super.initState();
_value = 0;
title = "any thing";
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
elevation: 0,
child: Icon(FontAwesomeIcons.plus),
onPressed: () {
setState(() {
_value++; // increment value here
});
},
),
);
}
}
If you need to get variables (value & title) from other class, then you need to:
Mark them as final, or
Get them from constructor
To access their values in _BottomCardStateState, you can access them using widget._value. They are final so you can't modify them. For example:
class App extends StatelessWidget {
const App({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: BottomCardState(2,"some thing"),
);
}
}
class BottomCardState extends StatefulWidget {
final int _value;
final String title;
BottomCardState(this._value,this.title)
#override
_BottomCardStateState createState() => _BottomCardStateState();
}
class _BottomCardStateState extends State<BottomCardState> {
int value ;
#override
Widget build(BuildContext context) {
value = widget._value ;
return Scaffold(
floatingActionButton: FloatingActionButton(
elevation: 0,
child: Icon(FontAwesomeIcons.plus),
onPressed: () {
setState(() {
value++; // increment value here
});
},
),
);
}
}
If I am declaring the variables as final then then the values(variables) i want to change(on pressed) are in set state(){} so those variables can be changed What to do to prevent this?
Extend StatefulWidget.
Also why is it written widget.value?
This means you are accessing value in your StatefulWidget subclass and this value is actually defined in your State class.
Full code should look like:
class BottomCardState extends StatefulWidget {
#override
_BottomCardStateState createState() => _BottomCardStateState();
}
class _BottomCardStateState extends State<BottomCardState> {
int _value = 0; // set value here
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
elevation: 0,
child: Icon(FontAwesomeIcons.plus),
onPressed: () {
setState(() {
_value++; // increment value here
});
},
),
);
}
}
Just added this line top of the error class.
//ignore: must_be_immutable