Dropdown resets all fields in Flutter - flutter

I am currently working on a tasks app. Whenever I select the priority from the drop down or the date the values in the text fields above get resets to null, and also the selected date and priority are set back to default.
Would really like some help on the same.
Code snippet is below -
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:ssms_new/Models/ToDoModel.dart';
import 'package:http/http.dart' as http;
import 'package:date_time_picker/date_time_picker.dart';
import 'package:ssms_new/Tasks/AllTasksTabsView.dart';
import '../Configurations/configurations.dart';
class AddTaskModalSheet extends StatefulWidget {
const AddTaskModalSheet({Key? key}) : super(key: key);
#override
_AddTaskModalSheetState createState() => _AddTaskModalSheetState();
}
class _AddTaskModalSheetState extends State<AddTaskModalSheet> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
var screenHeight = MediaQuery.of(context).size.height;
var screenWidth = MediaQuery.of(context).size.width;
final TextEditingController taskTitle = TextEditingController();
final TextEditingController taskNotes = TextEditingController();
String selectedPriority = "Normal";
String _dueDate = "${DateTime.now().toString()}";
Future<ToDoModel?> postNewTask() async {
var response;
String encodedPath = "task/new/$savedUserID";
if (devMode == "development") {
response = await http.post(Uri.parse('$devUrl$encodedPath'), body: {
"name": taskTitle.text,
"note": taskNotes.text,
"title": taskTitle.text,
"done": "0",
"priority": "$selectedPriority",
"due_date": "$_dueDate",
"TaskOwner": "$savedUserID",
"img": "NA",
"studentId": "$savedUserID",
"assignerId": "0",
"closeTaskNotes": "NA",
});
} else {
print(selectedPriority);
response = await http.post(Uri.parse('$prodUrl$encodedPath'), body: {
"name": taskTitle.text,
"note": taskNotes.text,
"title": taskTitle.text,
"done": "0",
"priority": "$selectedPriority",
"due_date": "$_dueDate",
"TaskOwner": "$savedUserID",
"img": "NA",
"studentId": "$savedUserID",
"assignerId": "0",
"closeTaskNotes": "NA",
});
}
print(response.statusCode);
String responseString = response.body;
toDoFromJson(responseString);
print(response.body);
return null;
}
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
color: Color(0xff737373),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
),
child: Column(children: [
SizedBox(height: 20),
Text(
"Add New Task",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
SizedBox(height: 20),
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
TextField(
controller: taskTitle,
decoration: InputDecoration(
labelText: "Task Title",
border: OutlineInputBorder(),
),
),
SizedBox(height: 10),
TextField(
controller: taskNotes,
maxLines: 3,
decoration: InputDecoration(
labelText: "Task Notes",
border: OutlineInputBorder(),
),
),
],
),
),
SizedBox(height: 2),
Container(
padding: EdgeInsets.only(left: 4, right: 3),
width: screenWidth / 1.05,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey, width: 2),
borderRadius: BorderRadius.circular(5)),
child: DropdownButtonFormField(
items: priorityList.map((String category) {
return DropdownMenuItem(
value: category,
child: Row(
children: <Widget>[
Text(category),
],
));
}).toList(),
onTap: () =>
FocusManager.instance.primaryFocus!.unfocus(),
onChanged: (newValue) {
// do other stuff with _category
selectedPriority = newValue.toString();
},
value: selectedPriority,
),
),
DateTimePicker(
type: DateTimePickerType.date,
dateMask: 'd MMM, yyyy',
initialValue: DateTime.now().toString(),
firstDate: DateTime.now(),
lastDate: DateTime(2100),
icon: Icon(Icons.event),
dateLabelText: 'Date',
onChanged: (val) {
_dueDate = val;
},
onSaved: (val) {
_dueDate = val!;
},
), //Select Work Date
SizedBox(height: 10),
ElevatedButton(
style:
ElevatedButton.styleFrom(primary: Color(0xffe9c46a)),
onPressed: () {
postNewTask();
Navigator.pushAndRemoveUntil(context,
MaterialPageRoute(builder: (context) {
return AllTasksTabView(id: savedUserID);
}), (route) => true);
}, //TODO: add task here
child: Text("Add Task",
style: TextStyle(color: Colors.black))),
SizedBox(height: 30),
]),
),
),
),
),
),
);
}
}

You are storing all your state inside the build method, so whenever the widget is rebuilt, all the state is overwritten.
Please take a look at this tutorial to understand the difference between StatefulWidget and StatelessWidget and how to add interactivity/

Related

Flutter Search Bar with ListView with Checkboxes

I want to create a widget like this.
This contains the Textfield, Once type something in the field, It will be sorting the list and show the results below the field. The result list shown below can also have a checkbox field to select multiple items from the result.
Is there any built-in flutter widget that can be useful for this case?
Or any other package to achieve this.
Following is the screenshot for reference.
I tried with RawAutoComplete widget.
Here is the code.
class SearchBarDemo extends StatelessWidget {
const SearchBarDemo({super.key});
static List<String> suggestons = [
"USA",
"UK",
"Uganda",
"Uruguay",
"United Arab Emirates"
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: RawAutocomplete(
optionsBuilder: (textEditingValue) {
if (textEditingValue.text == '') {
return const Iterable<String>.empty();
} else {
List<String> matches = <String>[];
matches.addAll(suggestons);
matches.retainWhere((s) {
return s
.toLowerCase()
.contains(textEditingValue.text.toLowerCase());
});
return matches;
}
},
fieldViewBuilder:
(context, textEditingController, focusNode, onFieldSubmitted) {
return TextField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(7),
),
hintText: 'Search',
contentPadding: EdgeInsets.symmetric(
vertical: 8,
horizontal: 4), // EdgeInsets.only(top: 8, left: 5),
prefixIcon: Container(
margin: EdgeInsets.symmetric(vertical: 8, horizontal: 4),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
border: Border(
right: BorderSide(
color: Colors.grey.shade400,
),
),
),
child: Icon(
Icons.search,
color: Colors.grey.shade400,
),
),
),
controller: textEditingController,
focusNode: focusNode,
onSubmitted: (String value) {},
);
},
onSelected: (selection) {},
optionsViewBuilder: (context, onSelected, options) {
return Material(
child: SingleChildScrollView(
child: Column(
children: options.map((opt) {
return InkWell(
onTap: () {
onSelected(opt);
},
child: Column(
children: [
Container(
height: 50,
width: 250,
alignment: Alignment.topLeft,
child: Card(
child: SizedBox(
child: ListTile(
title: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
opt,
style: TextStyle(fontSize: 12),
),
Transform.scale(
scale: 0.8,
child: Checkbox(
value: false,
onChanged: (val) {},
),
),
],
),
),
),
),
),
],
),
);
}).toList(),
),
),
);
},
),
);
}
}
Output of the above code is:
It covers the whole screen and show the result content in center.
You can customize the filter logic. Also you may like SearchDelegate-class
class SearchBarDemo extends StatefulWidget {
const SearchBarDemo({super.key});
#override
State<SearchBarDemo> createState() => _SearchBarDemoState();
}
class _SearchBarDemoState extends State<SearchBarDemo> {
static List<String> suggestons = [
"USA",
"UK",
"Uganda",
"Uruguay",
"United Arab Emirates"
];
List<String> filterItems = [];
List<String> checkedItems = [];
late final TextEditingController controller = TextEditingController()
..addListener(() {
/// filter logic will be here
final text = controller.text.trim();
filterItems = suggestons
.where(
(element) => element.toLowerCase().startsWith(text.toLowerCase()))
.toList();
setState(() {});
});
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
CupertinoTextField(
controller: controller,
),
Expanded(
child: ListView.builder(
itemCount: filterItems.length,
itemBuilder: (context, index) {
final bool isChecked =
checkedItems.contains(filterItems[index]);
return CheckboxListTile(
value: isChecked,
title: Text("${filterItems[index]}"),
onChanged: (value) {
if (isChecked) {
checkedItems.remove(filterItems[index]);
} else {
checkedItems.add(filterItems[index]);
}
setState(() {});
},
);
}),
),
],
));
}
}

how to refresh page after send POST API in flutter

I have a POST API that when I send a request, I give the GET API request on the same screen to show the json data.
When I send information, after sending the information, the Get data is not displayed and must be logged out to display GET API data.
How can I refresh the page after sending the POST API data, so that the information is displayed after sending
POST API:
void ladderAsli() async {
if (_avgWeeklySales.text.isNotEmpty) {
print(token);
var response = await http.post(
Uri.parse("localhost/backend/api/v1/pellekan/main/add/"),
body: ({
"avgWeeklySales": _avgWeeklySales.text,
}),
headers: {
'Authorization': 'Bearer $token',
});
var body = jsonDecode(response.body);
if (response.statusCode == 200) {
SharedPreferences pref = await SharedPreferences.getInstance();
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('${body['success']}')));
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('${body['error']}')));
}
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('error')));
}
}
and GET API:
Future getDataLadder() async {
print('bye');
String token = await getToken();
var response = await http.get(
Uri.parse('localhost/backend/api/v1/pellekan/main/active'),
headers: {
'Content-type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $token',
});
print('Token : ${token}');
print('Response Body : ${response.body}');
if (response.statusCode == 400) {
var chieIN = jsonDecode(response.body);
print("be moshkel khordim hich dataei nist");
}
if (response.statusCode == 200) {
var chieIN = jsonDecode(response.body);
// print('Hosssssein ' +
// chieIN['pellekanInfo']['pellekanPublishStatus'].toString());
val = chieIN['pellekanInfo']['pellekanPublishStatus'].toString();
print('BODOBA : ${val}');
setState(() {
val = '0';
});
//setState(() {
// stringResponse = jsonDecode(response.body)['pellekan'];
// val!.add(chieIN['pellekanInfo']['pellekanPublishStatus'].toString());
stringResponse = [];
stringResponse.addAll(List<NardebanData>.from(json
.decode(response.body)['pellekan']
.map((x) => NardebanData.fromJson(x))));
print('String Response : ${stringResponse}');
// nardeban_data = (stringResponse as List<NardebanData>).map((d) => NardebanData.fromJson(d)).toList();
//});
} else {
print("error");
}
}
in the initState call getDataLadder()
Refreshpage
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:project/pattern_formatter.dart';
import 'package:project/screens/result-ladder.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
List<NardebanData> nardeban_data = [];
List<NardebanData> stringResponse = [];
class Ladder extends StatefulWidget {
const Ladder({Key? key}) : super(key: key);
#override
_LadderState createState() => _LadderState();
}
Future<String> getToken() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString('login')!;
}
class _LadderState extends State<Ladder> {
bool value = true;
String? val = "";
String token = "";
#override
void initState() {
super.initState();
getDataLadder();
getInfo();
}
void getInfo() async {
SharedPreferences pref = await SharedPreferences.getInstance();
setState(() {
token = pref.getString("login")!;
});
}
TextEditingController _avgWeeklySales = TextEditingController();
TextEditingController _doubleSellingPricePercent = TextEditingController();
TextEditingController _tripleSellingPricePercent = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Directionality(
textDirection: TextDirection.rtl, child: gochgochApp()));
}
Future getDataLadder() async {
print('bye');
String token = await getToken();
var response = await http.get(
Uri.parse('localhost/backend/api/v1/pellekan/main/active'),
headers: {
'Content-type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $token',
});
print('Token : ${token}');
print('Response Body : ${response.body}');
if (response.statusCode == 400) {
var chieIN = jsonDecode(response.body);
print("be moshkel khordim hich dataei nist");
}
if (response.statusCode == 200) {
var chieIN = jsonDecode(response.body);
// print('Hosssssein ' +
// chieIN['pellekanInfo']['pellekanPublishStatus'].toString());
val = chieIN['pellekanInfo']['pellekanPublishStatus'].toString();
print('BODOBA : ${val}');
setState(() {
val = '0';
});
//setState(() {
// stringResponse = jsonDecode(response.body)['pellekan'];
// val!.add(chieIN['pellekanInfo']['pellekanPublishStatus'].toString());
stringResponse = [];
stringResponse.addAll(List<NardebanData>.from(json
.decode(response.body)['pellekan']
.map((x) => NardebanData.fromJson(x))));
print('String Response : ${stringResponse}');
// nardeban_data = (stringResponse as List<NardebanData>).map((d) => NardebanData.fromJson(d)).toList();
//});
} else {
print("hooooooooooooooooooooooooo");
}
}
// Future asyncokeyeData() async {
// SharedPreferences pref = await SharedPreferences.getInstance();
// val = pref.getString('okeyeData');
// }
Widget gochgochApp() {
print('Valiable : ${val}');
if (val == '0') {
print(val);
// return Container(
// height: 200.0,
// child: Center(child: Text('شما در انتظار تایید نیست')),
// );
// return alertInForProcessLadder();
return getBody();
// return getBody();
}
// if (val == '2' || val == null) {
// return getForm();
// }
else {
return getForm();
}
}
Widget alertInForProcessLadder() {
return (SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 24),
child: SingleChildScrollView(
child: Container(
child: Center(
child: Text(
'شما یک پلکان اصلی در انتظار تایید ادمین دارید و نمی توانید پلکان دیگری ایجاد کنید')),
height: 200.0,
),
)),
));
}
Widget getForm() {
return (SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 24),
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 9,
),
Text(
"فرم نردبان اصلی",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 18,
color: Colors.blue,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 10,
),
Container(
padding: EdgeInsets.all(28),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: [
Text(
'مبلغ را به تومان وارد کنید',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 13,
color: Colors.black54,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 4,
),
TextField(
controller: _avgWeeklySales,
textAlign: TextAlign.center,
cursorColor: Colors.blue,
keyboardType: TextInputType.number,
inputFormatters: [ThousandsFormatter()],
decoration: InputDecoration(
hintStyle:
TextStyle(color: Colors.black26, fontSize: 13),
hintText: 'مثال : 1,000,000',
border: OutlineInputBorder(),
hintTextDirection: TextDirection.rtl,
contentPadding: EdgeInsets.all(8),
),
),
SizedBox(
height: 22,
),
Text(
'درصد تخفیف برای 20 عدد',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 13,
color: Colors.black54,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 4,
),
TextField(
controller: _doubleSellingPricePercent,
textAlign: TextAlign.center,
cursorColor: Colors.blue,
keyboardType: TextInputType.number,
inputFormatters: [ThousandsFormatter()],
decoration: InputDecoration(
hintStyle:
TextStyle(color: Colors.black26, fontSize: 13),
hintText: 'مثال : 20',
border: OutlineInputBorder(),
hintTextDirection: TextDirection.rtl,
contentPadding: EdgeInsets.all(8),
),
),
SizedBox(
height: 22,
),
Text(
'درصد تخفیف برای 30 عدد',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 13,
color: Colors.black54,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 4,
),
TextField(
controller: _tripleSellingPricePercent,
textAlign: TextAlign.center,
cursorColor: Colors.blue,
keyboardType: TextInputType.number,
inputFormatters: [ThousandsFormatter()],
decoration: InputDecoration(
hintStyle:
TextStyle(color: Colors.black26, fontSize: 13),
hintText: 'مثال : 30',
border: OutlineInputBorder(),
hintTextDirection: TextDirection.rtl,
contentPadding: EdgeInsets.all(8),
),
),
SizedBox(
height: 25,
),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
ladderAsli();
},
style: ButtonStyle(
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
),
foregroundColor:
MaterialStateProperty.all<Color>(Colors.white),
backgroundColor:
MaterialStateProperty.all<Color>(Colors.blue),
),
child: Padding(
child: Text(
'تایید',
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 21),
),
padding: EdgeInsets.all(15.0),
),
),
),
],
),
),
],
),
)),
));
}
Widget getBody() {
var size = MediaQuery.of(context).size;
return Container(
width: size.width,
height: size.height,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10)),
color: Colors.white),
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Container(
height: 1,
decoration:
BoxDecoration(color: Colors.grey.withOpacity(0.2)),
),
),
SizedBox(
width: 10,
),
buildHeader(
text: 'جهت فعال سازی پله 30 عددی فیلد زیر را فعال کنید',
child: buildSwitch(),
),
SizedBox(
width: 10,
),
Flexible(
child: Container(
height: 1,
decoration:
BoxDecoration(color: Colors.grey.withOpacity(0.2)),
),
),
],
),
SizedBox(
height: 15,
),
Column(
children: List.generate(stringResponse.length, (index) {
NardebanData dataItem = stringResponse[index];
return Column(
children: [
Padding(
padding: const EdgeInsets.only(right: 5, left: 5),
child: Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage("assets/images/bg.png"),
fit: BoxFit.fill,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: 90,
// width: (size.width - 20) * 0.68,
child: Row(
children: [
SizedBox(width: 20), // give it width
Container(
width: 60,
decoration: BoxDecoration(
color: Colors.blue,
border:
Border.all(color: Colors.blue),
borderRadius:
BorderRadius.circular(40.0)),
child: Padding(
padding: EdgeInsets.all(10.0),
child: Text(dataItem.name!,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12.5,
fontWeight: FontWeight.bold,
color: Colors.white)))),
SizedBox(
width: 10,
),
Container(
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
dataItem.form ?? '' + '',
style: TextStyle(
fontSize: 14,
color: Colors.black54,
fontWeight: FontWeight.w400),
overflow: TextOverflow.ellipsis,
),
],
),
),
Container(
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
' تا ' + dataItem.to!,
style: TextStyle(
fontSize: 14,
color: Colors.black54,
fontWeight: FontWeight.w400),
overflow: TextOverflow.ellipsis,
),
],
),
)
],
),
),
Container(
width: (size.width - 120) * 0.32,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.blue)),
child: Padding(
padding: const EdgeInsets.only(
right: 10,
bottom: 4,
left: 10,
top: 4),
child: Row(
children: [
SizedBox(
width: 25,
height: 25,
child: TextField(
textAlign: TextAlign.center,
keyboardType:
TextInputType.number,
decoration: InputDecoration(
hintText: dataItem.percent!,
border: InputBorder.none,
contentPadding: EdgeInsets.only(
bottom: 8,
top: 3,
),
),
),
)
],
),
),
),
// Icon(
// Icons.notifications,
// size: 22,
// color: Colors.blue.withOpacity(0.7),
// )
],
),
)
],
),
)),
],
);
})),
],
),
),
);
}
Widget buildHeader({
required Widget child,
required String text,
}) =>
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
text,
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
),
const SizedBox(height: 3),
child,
],
);
Widget buildSwitch() => Transform.scale(
scale: 2,
child: Switch.adaptive(
activeColor: Colors.blueAccent,
activeTrackColor: Colors.blue.withOpacity(0.4),
// inactiveThumbColor: Colors.orange,
// inactiveTrackColor: Colors.black87,
splashRadius: 50,
value: value,
onChanged: (value) => setState(() => this.value = value),
),
);
void ladderAsli() async {
if (_avgWeeklySales.text.isNotEmpty) {
print(token);
var response = await http.post(
Uri.parse("localhost/backend/api/v1/pellekan/main/add/"),
body: ({
"avgWeeklySales": _avgWeeklySales.text,
"doubleSellingPricePercent": _doubleSellingPricePercent.text,
"tripleSellingPricePercent": _tripleSellingPricePercent.text,
}),
headers: {
'Authorization': 'Bearer $token',
});
var body = jsonDecode(response.body);
if (response.statusCode == 200) {
SharedPreferences pref = await SharedPreferences.getInstance();
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('${body['success']}')));
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('${body['error']}')));
}
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('مبلغ کل را وارد کنید')));
}
}
}
this is json sample:
{
"pellekan": [
{
"name": "پله 1",
"form": null,
"to": "9999",
"percent": 1
},
{
"name": "پله 2",
"form": "9999",
"to": 10.74,
"percent": 2.89
},
{
]
}
Listview.builder widget used to propagate the change in ui
ListView.builder(
itemCount: datajson!.length,
itemBuilder: (context, index) {
return Text(datajson![index].toString(),
style: TextStyle(fontSize: 10));
})
Here i use sample post and getmethod with future delay like mimic the api wait and supply the data.
void MygetData() {
Future.delayed(Duration(seconds: 3), () {
setState(() {
isloading = false;
datajson;
});
});
}
void posts() {
Future.delayed(Duration(seconds: 3), () {
// other post request
datajson?.add({"name": "2"});
MygetData();
});
}
SampleCode dartpad live
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
int myvalue = 0;
List<Map<String, dynamic>>? datajson = [];
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
bool isloading = false;
#override
void initState() {
isloading = true;
Future.delayed(Duration(seconds: 3), () {
setState(() {
datajson?.add({"name": "1"});
isloading = false;
});
});
}
void MygetData() {
Future.delayed(Duration(seconds: 3), () {
setState(() {
isloading = false;
datajson;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
// shrinkWrap: true,
children: [
Container(
height: 45,
child: ElevatedButton(
onPressed: () {
setState(() {
isloading = true;
});
posts();
},
child: Text(
"Post",
style: TextStyle(fontSize: 10),
)),
),
Expanded(
child: ListView.builder(
itemCount: datajson!.length,
itemBuilder: (context, index) {
return Text(datajson![index].toString(),
style: TextStyle(fontSize: 10));
}),
),
isloading
? Container(
height: 50,
width: 50,
child: CircularProgressIndicator(),
)
: Text("")
],
),
);
}
void posts() {
Future.delayed(Duration(seconds: 3), () {
// other post request
datajson?.add({"name": "2"});
MygetData();
});
}
}
i think best and easy way to solve this problem.
Navigator.push(context,MaterialPageRoute(builder: (context) =>yourclass()));
but you should fetch data in initstate like this.
void initState() { fetchYourItems(); super.initState(); };

How to display the value chosen?

The value that I chose from the DropdownMenuItem (eg: Malaysia (+06) ), the chosen value will be displayed, however, when I navigate back or proceed to other interfaces, it will disappear.
Problem:
How to make the chosen value maintained at the dropdown button box?
Is it any solution to solve the problem?
Below is my code segment inside showModalBottomSheet:
String _selectedCountryCode;
List jsonResult = List();
loadJsonData() async {
String data = await rootBundle.loadString('assets/country_code.json');
jsonResult = json.decode(data);
print(jsonResult);
}
#override
void initState() {
super.initState();
loadJsonData();
phoneController = TextEditingController();
}
Widget Part
Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
TextButton(
onPressed: () {
_showModalPhoneWidget();
},
child: Text(
"Request OTP", style: TextStyle(
color: const Color(0xff002aff),
fontSize: 15,
),
),)
],
)
_showModalPhoneWidget method part
_showModalPhoneWidget() {
showModalBottomSheet(
backgroundColor: Colors.green,
context: context,
isDismissible: true,
//transitionAnimationController: Duration(milliseconds: 400),
builder: (context) {
return StatefulBuilder(
builder: (context, setStateSTB) => ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
topRight: Radius.circular(10.0)),
child: Container(
height: 250,
color: Colors.white,
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 10.0),
child: Text(
"Update Phone",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
),
Padding(
padding: EdgeInsets.only(top: 20.0, left: 10.0),
child: Row(
children: <Widget>[
Text(
"Tel No",
style:
TextStyle(color: Colors.black, fontSize: 15.0),
),
Text(
"*",
style: TextStyle(color: Colors.red, fontSize: 15.0),
),
],
),
),
Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
height: 50.0,
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(color: const Color(0xffededed))),
child: Stack(
children: <Widget>[
Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 5.0, left: 5.0),
height: 40.0,
width: 100.0,
child: DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: false,
child: DropdownButton(
// child: DropdownButton<Map<String, String>>(
isExpanded: true,
value: _selectedCountryCode,
selectedItemBuilder: (BuildContext context)
{
return jsonResult.map<Widget>((element) {
return Text("${element['dial_code']}", textAlign: TextAlign.center);
}).toList();
},
items: jsonResult.map((element) {
return DropdownMenuItem(
child: Text("${element['name']} (${element['dial_code']})", overflow: TextOverflow.clip, maxLines: 1,),
value: element['dial_code'],
);
}).toList(),
onChanged: (val) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
//* to change on dialog
setStateSTB(() {
_selectedCountryCode = val;
prefs.setString('_selectedCountryCode', _selectedCountryCode);
print('select code: $_selectedCountryCode' );
});
//* to change on StateLevel
setState(() {
_selectedCountryCode = val;
prefs.setString('_selectedCountryCode', _selectedCountryCode);
});
},
),
),
),
),
// if(_isEditingText)
Container(
width: 120,
height: 40,
child: TextField(
controller: phoneController,
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
], // Only numbers can be entered
textAlign: TextAlign.center,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Tel No. Ex:0133333333',
),
onSubmitted: (newPhoneNo) {
setState(() {
initialText = newPhoneNo;
_isEditingText = false;
});
},
),
),
Container(
height: 40,
width: 100,
child: InkWell(
onTap: () {
setState(() {
_isEditingText = true;
});
},
),
),
],
)
],
),
),
Container(
margin: EdgeInsets.all(20.0),
child: ButtonTheme(
minWidth: double.infinity,
height: 50,
child: OutlineButton(
child: Text("Continue",
style: TextStyle(color: Colors.amber, fontSize: 16)),
borderSide: BorderSide(
color: Colors.amber,
),
highlightElevation: 10.0,
onPressed: () {
},
),
),
),
],
),
),
),
);
});
}
and this is my local JSON data:
[
{
"name": "Malaysia",
"dial_code": "+60",
"code": "MY"
},
{
"name": "Afghanistan",
"dial_code": "+93",
"code": "AF"
},
{
"name": "Aland Islands",
"dial_code": "+358",
"code": "AX"
},
{
"name": "Albania",
"dial_code": "+355",
"code": "AL"
},
{
"name": "Algeria",
"dial_code": "+213",
"code": "DZ"
},
{
"name": "AmericanSamoa",
"dial_code": "+1684",
"code": "AS"
},
{
"name": "Andorra",
"dial_code": "+376",
"code": "AD"
},
{
"name": "Angola",
"dial_code": "+244",
"code": "AO"
},
{
"name": "Anguilla",
"dial_code": "+1264",
"code": "AI"
},
{
"name": "Antarctica",
"dial_code": "+672",
"code": "AQ"
},
{
"name": "Antigua and Barbuda",
"dial_code": "+1268",
"code": "AG"
},
{
"name": "Argentina",
"dial_code": "+54",
"code": "AR"
},
{
"name": "Armenia",
"dial_code": "+374",
"code": "AM"
},
{
"name": "Aruba",
"dial_code": "+297",
"code": "AW"
},
{
"name": "Australia",
"dial_code": "+61",
"code": "AU"
},
{
"name": "Austria",
"dial_code": "+43",
"code": "AT"
},
{
"name": "Azerbaijan",
"dial_code": "+994",
"code": "AZ"
},
{
"name": "Bahamas",
"dial_code": "+1242",
"code": "BS"
},
{
"name": "Bahrain",
"dial_code": "+973",
"code": "BH"
},
{
"name": "Bangladesh",
"dial_code": "+880",
"code": "BD"
},
{
"name": "Barbados",
"dial_code": "+1246",
"code": "BB"
},
{
"name": "Belarus",
"dial_code": "+375",
"code": "BY"
},
{
"name": "Belgium",
"dial_code": "+32",
"code": "BE"
},
]
For problem 1 you can have the Map for DropdownMenuItem. While showing only name and dial_code you can set child like
items: jsonResult.map((element) {
return DropdownMenuItem(
child: Text(
"${element['name']} ${element['dial_code']}"),
value: element,
);
}).toList(),
For problem 2 updating state on dialog needs to use StatefulBuilder and use its setstate to update on dialog, prefer renaming this.
return StatefulBuilder(
builder: (context, setStateSTB) => ClipRRect(
......
onChanged: (_selectedCountryCode) {
//* to change on dialog
setStateSTB(() {
_defaultCountryCode = _selectedCountryCode;
});
//* to change on StateLevel
setState(() {
_defaultCountryCode = _selectedCountryCode;
});
},
Update the issue was on loadJsonData()
Future<void> loadJsonData() async {
///
String data = await rootBundle.loadString('assets/country_code.json');
final jsonString = jsonDecode(data) as List;
final item = jsonString.map((e) {
return {
'name': e['name'] as String,
'dial_code': e['dial_code'] as String,
'code': e['code'] as String,
};
}).toList();
setState(() {
jsonResult = item;
});
}
Full snippet
class _TFTState extends State<TFT> {
Map<String, String>? _defaultCountryCode;
late List<Map<String, String>> jsonResult;
#override
void initState() {
super.initState();
loadJsonData();
}
Future<void> loadJsonData() async {
///
String data = await rootBundle.loadString('assets/country_code.json');
final jsonString = jsonDecode(data) as List;
final item = jsonString.map((e) {
return {
'name': e['name'] as String,
'dial_code': e['dial_code'] as String,
'code': e['code'] as String,
};
}).toList();
setState(() {
jsonResult = item;
});
}
final phoneController = TextEditingController();
_showModalPhoneWidget() {
showModalBottomSheet(
backgroundColor: Colors.green,
context: context,
isDismissible: true,
//transitionAnimationController: Duration(milliseconds: 400),
builder: (context) {
return StatefulBuilder(
builder: (context, setStateSTB) => ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
topRight: Radius.circular(10.0)),
child: Container(
height: 250,
color: Colors.white,
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 10.0),
child: Text(
"Update Phone",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
),
Padding(
padding: EdgeInsets.only(top: 20.0, left: 10.0),
child: Row(
children: <Widget>[
Text(
"Tel No",
style:
TextStyle(color: Colors.black, fontSize: 15.0),
),
Text(
"*",
style: TextStyle(color: Colors.red, fontSize: 15.0),
),
],
),
),
Container(
margin:
EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
height: 50.0,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: const Color(0xffededed))),
child: Row(
children: <Widget>[
DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton<Map<String, String>>(
value: _defaultCountryCode,
hint: Text("Hint textOn null"),
items: jsonResult.map((element) {
return DropdownMenuItem(
child: Text(
"${element['name']} ${element['dial_code']}"),
value: element,
);
}).toList(),
onChanged: (_selectedCountryCode) {
//* to change on dialog
setStateSTB(() {
_defaultCountryCode = _selectedCountryCode;
});
//* to change on StateLevel
setState(() {
_defaultCountryCode = _selectedCountryCode;
});
},
),
),
),
Container(
width: 250,
height: 40,
child: TextField(
controller: phoneController,
textAlign: TextAlign.start,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Tel No. Ex:0133333333',
),
),
),
],
),
),
Container(
margin: EdgeInsets.all(20.0),
child: ButtonTheme(
minWidth: double.infinity,
height: 50,
child: OutlineButton(
child: Text("Continue",
style:
TextStyle(color: Colors.amber, fontSize: 16)),
borderSide: BorderSide(
color: Colors.amber,
),
highlightElevation: 10.0,
onPressed: () {},
),
),
),
],
),
),
),
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
ElevatedButton(
onPressed: () {
// json loaded on initState
print(jsonResult.length);
_showModalPhoneWidget();
},
child: Text("s"),
)
],
),
);
}
}

When routing to another page I get "There are multiple heroes that share the same tag within a subtree"

I am trying to navigate from one screen to another with route. When I hit the button for the page to move to the route provided I get the error:
I/flutter ( 8790): Another exception was thrown: There are multiple heroes that share the same tag within a subtree.
Sharing with you the source code:
import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_counter/flutter_counter.dart';
import 'package:gender_selection/gender_selection.dart';
import 'package:group_chats/addContactUI.dart';
import 'package:group_chats/addPhone.dart';
import 'package:group_chats/letGoUI.dart';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'Animation/FadeAnimation.dart';
import 'Model/insertUserModel.dart';
class AddProfileUI extends StatefulWidget {
final List<String> listFriends;
final String phone;
AddProfileUI(this.listFriends, this.phone);
#override
_AddProfileUIState createState() => _AddProfileUIState();
}
class _AddProfileUIState extends State<AddProfileUI> {
File _image;
final picker = ImagePicker();
final _formKey = GlobalKey<FormState>();
String name = "";
String city = "";
TextEditingController dobController = TextEditingController();
bool single = false;
Gender gender;
final _scaffoldKey = GlobalKey<ScaffoldState>();
int defaultValue = 18;
List<String> selectedContact;
SharedPreferences prefs;
bool _loading = true;
Future initPrefs() async {
prefs = await SharedPreferences.getInstance();
}
uploadImage(String userId) async {
try {
FormData formData = new FormData.fromMap({
"file":
await MultipartFile.fromFile(_image.path, filename: "$userId.jpg"),
});
var response = await Dio().post(
"https://us-central1-app-backend-fc090.cloudfunctions.net/webApi/api/v1/upload_profile/$userId",
data: formData);
if (response.statusCode == 200)
return response.data;
else
return null;
} catch (e) {
print(e.toString());
return null;
}
}
Future<InsertUserModel> insertData() async {
try {
for (int i = 0; i < selectedContact.length; i++) {
if (selectedContact[i][0] == "0") {
selectedContact[i] = selectedContact[i].replaceRange(0, 1, "+972");
}
}
var body = jsonEncode({
"gender": gender.index == 0 ? "male" : "female",
"city": city,
"last_login": {},
"friends": selectedContact ?? [],
"single": single,
"name": name,
"phone_number": widget.phone,
"age": defaultValue
});
final String apiUrl =
"https://us-central1-app-backend-fc090.cloudfunctions.net/webApi/api/v1/users/${AddPhoneUI.uid}";
final response = await http.post(apiUrl,
headers: {"content-type": "application/json"}, body: body);
if (response.statusCode == 200) {
final responseString = response.body;
return insertUserModelFromJson(responseString);
}
} catch (e) {
setState(() {
_loading = false;
});
}
}
getUserData() async {
try {
final String apiUrl =
"https://us-central1-app-backend-fc090.cloudfunctions.net/webApi/api/v1/users/";
final response = await http.get(apiUrl);
if (response.statusCode == 200) {
final responseString = response.body;
return insertUserModelFromJson(responseString);
}
} catch (e) {
setState(() {
_loading = false;
});
Scaffold.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.red,
content: Text('Error: ${e.toString()}'),
duration: Duration(milliseconds: 2500),
));
}
}
Future<void> _selectStartingDate(BuildContext context) async {
DateTime selectedDate = DateTime.now();
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: DateTime(1950),
lastDate: DateTime(
DateTime.now().year, DateTime.now().month, DateTime.now().day),
);
if (picked != null && picked != selectedDate)
setState(() {
selectedDate = picked;
dobController.text = selectedDate.year.toString() +
"-" +
selectedDate.month.toString() +
"-" +
selectedDate.day.toString();
});
}
Future getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
_image = File(pickedFile.path);
});
}
showPopUp(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
shape:
OutlineInputBorder(borderRadius: BorderRadius.circular(14.0)),
content: Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
height: 20.0,
),
Text(
"My Profile",
style: TextStyle(
fontSize: 27.0, fontWeight: FontWeight.w600),
),
SizedBox(
height: 30.0,
),
RichText(
text: TextSpan(
text: "Your friends will be able to\nsee ",
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
),
children: <TextSpan>[
TextSpan(
text: 'only',
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.w500)),
TextSpan(text: 'your picture and\name.'),
],
)),
SizedBox(
height: 10.0,
),
RichText(
text: TextSpan(
text: "Other fields are used for\n",
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
),
children: <TextSpan>[
TextSpan(
text: 'research issues',
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.w500)),
TextSpan(text: "only."),
],
)),
SizedBox(
height: 10.0,
),
RichText(
text: TextSpan(
text: "Please fill all the fields.",
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
),
)),
SizedBox(
height: 80.0,
),
MaterialButton(
shape: OutlineInputBorder(
borderSide: BorderSide(width: 1.0)),
color: Colors.white38,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 20.0),
child: Text(
"Ok, got it",
style: TextStyle(fontSize: 18.0),
),
),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
));
}
#override
void initState() {
super.initState();
selectedContact = widget.listFriends;
initPrefs();
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
body: SafeArea(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(right: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {},
),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddContactUI(),
)).then((value) {
setState(() {
selectedContact = value;
});
});
},
child: Column(
children: [
Icon(
Icons.supervisor_account,
size: 40.0,
),
Text("Add Friends"),
],
),
)
],
),
),
Container(
child: GestureDetector(
onTap: () async {
await getImage();
},
child: CircleAvatar(
radius: 60.0,
backgroundImage: _image != null
? Image.file(_image).image
: Image.asset("assets/empty.png").image,
backgroundColor: Colors.transparent,
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: FadeAnimation(
1.7,
Form(
key: _formKey,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Color(0xff5E17EB).withOpacity(0.3),
blurRadius: 20,
offset: Offset(0, 10),
)
]),
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border(
bottom:
BorderSide(color: Colors.grey[200]))),
child: TextFormField(
textInputAction: TextInputAction.next,
onFieldSubmitted: (_) =>
FocusScope.of(context).nextFocus(),
onChanged: (val) {
setState(() {
name = val;
});
},
validator: (val) =>
val.isEmpty ? "Enter Name" : null,
decoration: InputDecoration(
border: InputBorder.none,
hintText: "Name",
hintStyle: TextStyle(color: Colors.grey)),
),
),
Container(
decoration: BoxDecoration(
border: Border(
bottom:
BorderSide(color: Colors.grey[200]))),
padding: EdgeInsets.all(10),
child: TextFormField(
textInputAction: TextInputAction.next,
keyboardType: TextInputType.text,
onChanged: (val) {
setState(() {
city = val;
});
},
validator: (val) {
if (val.isEmpty) return "Enter City";
// if (val.length < 6)
// return "Password should be at least 6 characters";
return null;
},
decoration: InputDecoration(
border: InputBorder.none,
hintText: "City",
hintStyle: TextStyle(color: Colors.grey)),
),
),
Container(
height: 140.0,
padding: EdgeInsets.all(10),
child: GenderSelection(
selectedGender: gender,
maleText: "", //default Male
femaleText: "", //default Female
linearGradient: LinearGradient(colors: [
Colors.indigo,
Colors.black
]), //List: [Colors.indigo, Colors.black]
selectedGenderIconBackgroundColor:
Colors.indigo, // default red
checkIconAlignment:
Alignment.centerRight, // default bottomRight
selectedGenderCheckIcon:
null, // default Icons.check
onChanged: (Gender gender) {
this.gender = gender;
print(this.gender);
},
equallyAligned: true,
animationDuration: Duration(milliseconds: 400),
isCircular: true, // default : true,
isSelectedGenderIconCircular: true,
opacityOfGradient: 0.6,
padding: const EdgeInsets.all(3),
size: 120, //default : 120
),
),
SizedBox(
height: 10.0,
),
Row(
children: [
Checkbox(
value: single,
onChanged: (value) {
setState(() {
single = !single;
});
},
),
Text(
"Are you Single?",
style: TextStyle(fontSize: 16.0),
)
],
),
Padding(
padding: const EdgeInsets.all(14.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
"Age:",
style: TextStyle(fontSize: 18.0),
),
Counter(
initialValue: defaultValue,
buttonSize: 35.0,
textStyle: TextStyle(fontSize: 25.0),
minValue: 0,
color: Colors.black,
maxValue: 80,
step: 1,
decimalPlaces: 0,
onChanged: (value) {
// get the latest value from here
setState(() {
defaultValue = value;
});
},
),
],
),
),
],
),
),
),
),
),
SizedBox(
height: 20.0,
),
FadeAnimation(
1.9,
MaterialButton(
shape: OutlineInputBorder(borderSide: BorderSide(width: 1.0)),
color: Colors.black,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 20.0),
child: Text(
"Next",
style: TextStyle(
fontSize: 18.0,
color: Colors.white,
),
),
),
onPressed: () async {
if (_formKey.currentState.validate()) {
InsertUserModel result = await insertData();
// var imageResult = await uploadImage(result.id);
print(result.data[0].id);
if (_image != null) {
await uploadImage(result.data[0].id);
}
setState(() {
_loading = false;
});
if (result != null) {
await prefs.setString("userID", result.data[0].id);
final snackBar = SnackBar(
content: Text(
result.message,
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.green,
duration: Duration(milliseconds: 2000),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LetGoUI(result.data[0].id),
));
} else {
final snackBar = SnackBar(
content: Text(
"Here is some error, please try again later!",
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.red,
duration: Duration(milliseconds: 2000),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
}
},
),
)
],
),
),
),
);
}
}
I really don't understand what is the problem because I'm not using any Heros and not have double FloatingActionButton.
How do I solve this?
Thanks
There might be problem with showing snackbar while navigating. you should remove that problem by calling following method before navigating.
void removeSnackBarCallsBeforeNavigation() {
ScaffoldMessenger.of(context).removeCurrentSnackBar();
}

Getting values from all TextFeilds in ListView

I made a widget consisting of a ListView with three TextFields per item like this.
The widget can contain N addresses as the contact has. When the contact finishes entering their addresses I want to click the save button in appBar to get all the input values from each item of ListView and put in JSON. Something like this:
[
{"Place": "Office", "Street": "Street Name", "PostalCode": "56789"},
{"Place": "Home", "Street": "Street Home", "PostalCode": "57689"},
{"Second Home": "Office", "Street": "Street 2th", "PostalCode": "45342"},
]
This is the code of the widget:
class TestPage2 extends StatefulWidget {
#override
_TestPage2State createState() => _TestPage2State();
}
class _TestPage2State extends State<TestPage2> {
List<Widget> lwidgets = [];
#override
void initState() {
lwidgets.insert(
lwidgets.length,
_Contacts(
indice: 0, onDeleteContact: (int i) => {deleteItemFromList(i)}));
lwidgets.insert(lwidgets.length, _AddElement(() => {addItemToList()}));
super.initState();
}
void addItemToList() {
setState(() {
lwidgets.insert(
lwidgets.length - 1,
_Contacts(
indice: lwidgets.length - 1,
onDeleteContact: (int i) => {deleteItemFromList(i)}));
});
}
void deleteItemFromList(int i) {
setState(() {
lwidgets.removeAt(i);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('CONTACTS'),
leading: Icon(Icons.arrow_left),
actions: <Widget>[
FlatButton(
onPressed:
() {}, // I want get all values contained of lwidgets. What do i need to do???
child: Text(
'SAVE',
style: TextStyle(color: Colors.white),
),
)
],
),
backgroundColor: Color(0xFFE5E5EA),
body: Column(
children: <Widget>[
Text('ADRESSES'),
Container(
height: 200,
child: ListView.builder(
itemCount: lwidgets.length,
itemBuilder: (BuildContext context, int index) {
return lwidgets[index];
},
physics: NeverScrollableScrollPhysics(),
),
),
],
));
}
}
This is the code of contact info widget:
class _Contacts extends StatelessWidget {
final int indice;
final Function(int) onDeleteContact;
const _Contacts({this.indice = 0, this.onDeleteContact});
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
height: 40,
color: Colors.white,
child: Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.remove_circle),
iconSize: 24,
color: Color(0xFFFF3B30),
onPressed: () {
onDeleteContact(indice);
},
),
Container(
width: 100,
child: TextField(
decoration: InputDecoration(
hintText: 'Place',
border: InputBorder.none,
),
style: TextStyle(fontFamily: 'Lekton'),
),
),
_VerticalDivider(),
Container(
width: 100,
child: TextField(
decoration: InputDecoration(
hintText: 'Street',
border: InputBorder.none,
),
style: TextStyle(fontFamily: 'Lekton'),
),
),
_VerticalDivider(),
Container(
width: 100,
child: TextField(
decoration: InputDecoration(
hintText: 'Postal Code',
border: InputBorder.none,
),
style: TextStyle(fontFamily: 'Lekton'),
),
),
],
),
),
_HorizontalDivider(),
],
);
}
I will be grateful for any help