Displaying complex json in FormBuilderRadioGroup in flutter_form_builder flutter - json

I'm having trouble displaying 'option' and getting (print in terminal) the 'id' of the chosen option.
How can I retrieve the json as map and use it effectively in flutter_form_builder?
Here is the json object:
{
id: 7,
poll: What is the capital of Egypt?,
created_at: 2020-10-22 10:53:41,
votes_count: 4,
likes_count: 0,
options: [
{
id: 20,
option: Tunis,
pollId: 7,
votes_count: 1
}, {
id: 21,
option: Cairo,
pollId: 7,
votes_count: 3
}, {
id: 22,
option: New York,
pollId: 7,
votes_count: 0
}],
user_name: salem,
user_image: null,
topics: []
}
Here is my poll_details page:
import 'package:flutter/material.dart';
import 'package:circular_profile_avatar/circular_profile_avatar.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:like_button/like_button.dart';
import '../services/poll_services.dart';
import '../widgets/loading_widget.dart';
class PollDetails extends StatefulWidget {
final id;
PollDetails({this.id});
#override
_PollDetailsState createState() => _PollDetailsState(id);
}
class _PollDetailsState extends State<PollDetails> {
var id;
_PollDetailsState(this.id);
final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
#override
void initState() {
super.initState();
optionsList.clear();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(title: Text("Details")),
body: FutureBuilder(
future: singlePoll(id),
builder: (context, snapshot) {
if(snapshot.hasData){
return ListView(
padding: EdgeInsets.fromLTRB(18, 40, 18, 0),
children: [
Padding(
padding: EdgeInsets.only(bottom: 20),
child: Container(
padding: EdgeInsets.fromLTRB(10, 40, 0, 40),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10.0),
border: Border.all(
color: Theme.of(context).primaryColor,
width: 5.0,
style: BorderStyle.solid
)
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
if(imgPath(snapshot.data) == null) CircleAvatar(radius: 35,child: Image.asset('images/avatar.png'))
else CircularProfileAvatar(
imgPath(snapshot.data),
radius: 35,
borderWidth: 3.0,
borderColor: Colors.white,
backgroundColor: Colors.transparent,
foregroundColor: Colors.transparent,
errorWidget: (context, url, error) => Container(child: Icon(Icons.error)),
placeHolder: (context, url) => Container(
width: 50,
height: 50,
child: Text("Loading image..."),
)
),
SizedBox(width: 10.0),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
userName(snapshot.data),
style: TextStyle(fontSize: 20)
),
Flexible(
fit: FlexFit.loose,
child: Text(
votesCount(snapshot.data).toString()+" participants to this poll",
style: TextStyle(fontSize: 13)
)
)
]
)
)
]
)
)
),
///////////////////////////////// POLLS //////////////////////////////////////////////
FormBuilder(
key: _fbKey,
autovalidateMode: AutovalidateMode.always,
child: FormBuilderRadioGroup(
attribute: 'options',
decoration: InputDecoration(labelText: 'Choose only one:'),
validators: [FormBuilderValidators.required()],
orientation: GroupedRadioOrientation.vertical,
options: [
for (var i in optionsList) i['option'].toString()
]
.map((option) => FormBuilderFieldOption(value: option))
.toList(growable: false),
)
),
RaisedButton(
child: Text("Submit"),
onPressed: () async{
_fbKey.currentState.save();
if (_fbKey.currentState.validate()) {
// Loading().show(context);
var option = _fbKey.currentState.value['options'];
print(option);
// var resp = await createPoll(question, tagS, choiceS);
// if(resp['status'] == "success"){
// Navigator.pop(context); //pop dialog
// } else {
// Navigator.pop(context); //pop dialog
// }
}
}
),
//////////////////////////// Like Button ///////////////////////////////
Row(
children: [
LikeButton(
size: 40,
circleColor:
CircleColor(start: Colors.red, end: Colors.red),
bubblesColor: BubblesColor(
dotPrimaryColor: Colors.red,
dotSecondaryColor: Colors.red,
),
likeBuilder: (bool isLiked) {
return Icon(
Icons.favorite,
color: isLiked ? Colors.red : Colors.grey,
size: 40,
);
},
likeCount: likes(snapshot.data),
countBuilder: (int count, bool isLiked, String text) {
var color = isLiked ? Colors.red : Colors.grey;
Widget result;
if (count == 0) {
result = Text(
"0",
style: TextStyle(color: color),
);
} else
result = Text(
text,
style: TextStyle(color: color),
);
return result;
}
),
Expanded(child: Text(" have liked this. Show some love, too!"))
]
),
Column(
children: [
// optionsList.forEach((element) => Text('option'))
for (var i in optionsList) Text(i['option'].toString())
]
),
RaisedButton(
child: Text("data"),
onPressed: (){singlePoll(id);}
)
]
);
}else {
return Center(child: CircularProgressIndicator());
}
}
)
)
);
}
}
And here is the request I use to get the response:
Future singlePoll(int id) async {
String url = baseUrl+"poll/get";
var stringID = id.toString();
var token = await storage.read(key: "jwt");
try{
final response = await http.post(
url,
headers: {'Accept':'application/json', 'Authorization':token},
body: {'pollId':stringID}
);
var dataToJson = jsonDecode(response.body);
for (var option in dataToJson['options']){
var optionID = option['id'];
var optionTitle = option['option'].toString();
var votesCount = option['votes_count'];
optionsList.add(option);
}
print(dataToJson);
return dataToJson;
} catch (e){
print('error caught: $e');
}
}
As you can see, I used a work around to get the list and display it.
Any suggestion is valuable.
Thanks in advance...

You need to use setState() in here:
setState() {
var optionID = option['id'];
var optionTitle = option['option'].toString();
var votesCount = option['votes_count'];
optionsList.add(option);
}
You can read more from the official document and look at here.

Related

RangeError (index): Index out of range: no indices are valid: 0 - Flutter

I'm new to flutter.
When I'm trying to add list data to the widget RealAppcard of Text
the list data is '${extractRooms[0]}'
I'm getting this error
RangeError (index): Index out of range: no indices are valid: 0
but without this data added everything is working
what am I doing wrong here?
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:gs/card_real_app.dart';
import 'package:gs/homescreen.dart';
import 'package:gs/network.dart';
import 'package:gs/pic_model.dart';
import 'package:gs/reusable_card.dart';
import 'package:dotted_border/dotted_border.dart';
import 'Custom_textfield.dart';
import 'order.dart';
import 'dart:convert' as convert;
import 'package:http/http.dart' as http;
import 'ordertile.dart';
const cardinactiveColor = Color(0xFF0a1529);
const cardActivecolor = Color(0xFFffb700);
var orderData;
// List<Order> orders = <Order>[];
List<Order> OrdersItems = [];
List<dynamic> feedbacks = [];
List<dynamic> pics = [];
late final String? picData;
late final String? statusData;
List<dynamic> filteredOrdersItems = [];
List<dynamic> feedbpics = [];
// final assetController = TextEditingController();
String currentSearch = '';
// String? statusOrder;
// String? picOrder;
// String? myStr = 'shalom';
List<dynamic> extractRooms = [];
List<dynamic> extractStatus = [];
List<dynamic> extractType = [];
List<dynamic> extractMap = [];
dynamic getRooms() {
filteredOrdersItems.forEach((item) {
extractRooms.insert(0, item.rooms);
// print('${item.pic}');
});
}
dynamic getType() {
filteredOrdersItems.forEach((item) {
extractType.insert(0, item.type);
// print('${item.pic}');
});
}
dynamic getSatausData() {
filteredOrdersItems.forEach((item) {
extractStatus.insert(0, item.status);
// print('${item.pic}');
});
}
dynamic getPicData() {
filteredOrdersItems.forEach((item) {
extractMap.insert(0, item.pic);
// print('${item.pic}');
});
}
var data;
var parsedJsonText = jsonDecode(data);
class searchScreen extends StatefulWidget {
// firstScreen({Key? key}) : super(key: key);
#override
State<searchScreen> createState() => _searchScreenState();
}
class _searchScreenState extends State<searchScreen> {
#override
void initState() {
super.initState();
getOrders().then((
OrderItems,
) {
setState(() {
// this.OrderItems = OrderItems;
// filteredOrdersItems = OrderItems;
});
});
}
// void initState() {
// super.initState();
// getOrders().then((
// feedbackItems,
// ) {
// setState(() {
// // this.feedbackItems = feedbackItems;
// // this.filteredFeedbackItems = feedbackItems;
// });
// });
// }
// List<OrderModel> orders = <OrderModel>[];
Color cardColor = cardinactiveColor;
void updateColor() {
if (cardColor == cardinactiveColor) {
cardColor = cardActivecolor;
} else {
cardColor = cardinactiveColor;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
// ignore: prefer_const_literals_to_create_immutables
Container(
height: 400,
color: Color(0xFF0a1529),
child: Column(
children: [
const Icon(
Icons.real_estate_agent_outlined,
color: Colors.white,
size: 80,
),
// data: Icons.real_estate_agent_outlined,
SizedBox(height: 5),
Text(
'ברוכים הבאים לאפליקצית חיפוש נכסים',
style: TextStyle(
fontSize: 20.0,
color: Colors.blue,
),
),
SizedBox(height: 15),
CustomTextField(
data: Icons.search,
// controller: null,
hintText: 'חיפוש נכס',
enabled: true,
// controller: assetController,
),
SizedBox(height: 15),
DottedBorder(
color: Color(0xFFffb700),
strokeWidth: 1,
child: Card(
color: Colors.transparent,
elevation: 0,
child: Container(
width: 400,
height: 140,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Padding(
padding: EdgeInsets.all(10.0),
child: Icon(
FontAwesomeIcons.crown,
// Icons.workspace_premium,
color: Color(0xFFffb700),
),
),
Padding(
padding: EdgeInsets.all(10.0),
child: Text(
'מיוחדים',
style: TextStyle(
color: Colors.white,
),
),
),
],
),
Text(
'מוזמנים להתנסות במערכת הנפלאה',
style: TextStyle(
color: Color(0xFF8d8e98),
),
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
GestureDetector(
onTap: () {},
child: Card(
color: cardColor,
child: Container(
child: Row(
children: [
ButtonTheme(
minWidth: 30.0,
height: 15.0,
child: RaisedButton(
color: Colors.amber,
child: Text(
'בצעו חיפוש',
style: TextStyle(
fontSize: 20,
),
),
onPressed: () async {
feedbacks = await getOrders();
// pics = await getPic();
// feedbpics =
// pics.where((element) {
// return element.id ==
// currentSearch;
// }).toList();
// print(feedbpics);
print(feedbacks);
filteredOrdersItems =
feedbacks.where((element) {
return element.address ==
currentSearch;
}).toList();
filteredOrdersItems
.forEach((item) {
print('${item.pic}');
});
// picData = getStatus();
// statusData = getPic();
// print('pic $picData');
// print('status $statusData');
// getPic();
getPicData();
getType();
getSatausData();
getRooms();
print(
'checking ${filteredOrdersItems[0]}');
print(
'list map${filteredOrdersItems}');
print('list $extractMap');
print(extractMap[0]);
print(
'status ${extractStatus[0]}');
print(
'rooms ${extractRooms[0]}');
// print(
// 'status ${extractMapStatus}');
setState(() {});
}),
),
// Text(
// 'בדקו עכשיו',
// style: TextStyle(
// color: Colors.white,
// ),
// ),
Icon(
FontAwesomeIcons.arrowRight,
// Icons.workspace_premium,
color: Color(0xFFffb700),
),
],
),
),
),
)
],
),
],
),
),
),
),
],
),
),
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
color: Colors.white,
elevation: 5,
child: Container(
width: 500,
height: 500,
decoration:
BoxDecoration(borderRadius: BorderRadius.circular(25)),
child: Column(
children: [
// Text('${feedbpics[0]}'),
if (filteredOrdersItems.isEmpty) ...{
Text(
"לא נמצאו תוצאות נסו שנית",
style: TextStyle(
fontSize: 20,
),
),
} else ...{
Text(
'${extractType[0]}',
style: TextStyle(
fontSize: 20,
),
),
SizedBox(height: 20),
Card(
elevation: 8,
child: Image.network(
'${extractMap[0]}',
width: 200,
height: 100,
),
),
},
// SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'כתובת מלאה',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Color(0xFFA435F0),
),
),
Text('ניקוד נכס'),
],
),
// SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
realAppCard(
text: 'חדרים',
quantity: '${extractRooms[0]}',
),
realAppCard(
text: 'גודל דירה',
quantity: '120',
),
realAppCard(
text: 'מחיר',
quantity: '1.5',
),
],
),
SizedBox(height: 10),
Card(
color: Colors.green,
elevation: 10,
child: Container(
width: 100,
height: 30,
child: Text(
'status',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
),
),
),
),
SizedBox(height: 5),
Center(
child: Text(
'''
הרשות פרסמה את ממצאי התחקיר שערכה על הרג כתבת אל ג'זירה,
ממנו עולה שהחיילים ירו בה בכוונה, למרות שראו שמדובר בעיתונאית.
לטענת התובע, הקליע, שהשימוש בו לא היה חוקי
''',
textAlign: TextAlign.center,
),
),
SizedBox(height: 5),
Card(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(10),
topRight: Radius.circular(10)),
side: BorderSide(width: 1, color: Colors.blueGrey)),
child: ListTile(
leading: Icon(Icons.message_outlined),
trailing: Text('משה כהן'),
title: Text('052-3567104'),
),
),
SizedBox(height: 5),
ElevatedButton(
onPressed: null,
child: Text('שליחת ווטסאפ'),
),
],
)),
// Center(
// child: Container(
// width: 300,
// child: TextField(
// decoration: const InputDecoration(
// border: OutlineInputBorder(), hintText: 'הקלידו הזמנה'),
// onChanged: (String newstr) {
// currentSearch = newstr;
// // print('first: ${currentSearch}');
// // print(newstr);
// // feedbackItems.forEach((element) {
// // print(element.status);
// // });
// },
// ),
// ),
// ),
// SizedBox(height: 20),
// ButtonTheme(
// minWidth: 200.0,
// height: 30.0,
// child: RaisedButton(
// color: Colors.amber,
// child: Text(
// 'בצעו חיפוש',
// style: TextStyle(
// fontSize: 20,
// ),
// ),
// onPressed: () async {
// feedbacks = await getOrders();
// print(feedbacks);
// filteredOrdersItems = feedbacks.where((element) {
// return element.id == currentSearch;
// }).toList();
// print(filteredOrdersItems);
// setState(() {});
// }),
// ),
// SizedBox(height: 10),
// ignore: sdk_version_ui_as_code
)
],
),
);
}
}
Future<List<dynamic>> getOrders() async {
String url =
'https://script.google.com/macros/s/AKfycbyT3xsBV2nrxgCotCA8-hyZ1DNTNt1ET0wuKilQZr29ac8pbpXMk7nMrCnz2_7NPW1j/exec';
var response = await http.get(Uri.parse(url));
var jsonData = convert.jsonDecode(response.body) as List;
String data = response.body;
// var parsedJson = json.decode(response.body);
// var orderModel = jsonDecode(data)[0]['pic'];
// print('this is my natun ${orderModel}');
// print('response body ${data}');
// print(jsonData);
return jsonData.map((json) => Order.fromJson(json)).toList();
// for (var order in jsonData) {
// OrdersItems.add(Order(order['id'], order['name'], order['status']));
// OrdersItems.forEach((element) {
// print("id : ${element.id}");
// });
// }
// // filteredOrdersItems =
// // OrdersItems.where((ord) => ord['id'] == 'test').toList();
// print(OrdersItems[1].id);
// print(OrdersItems);
// print(filteredOrdersItems);
// return OrdersItems;
}
// Future<List<dynamic>> getPic() async {
// String url =
// 'https://script.google.com/macros/s/AKfycbz12UnYLSmxvwGdeUH2EI7VQ8AnLMACE6IEy3bl3TcmhnyWa0Wmfxxr17swWWXCoXqd/exec';
// var response = await http.get(Uri.parse(url));
// var jsonData = convert.jsonDecode(response.body) as List;
// // print(jsonData);
// return jsonData.map((json) => Pic.fromJson(json)).toList();
// }
if you getting the error, it means one of the extractRoom throwing this is empty, so what you can do it check if the extractRoom is not empty before displaying its content.
realAppCard(
text: 'מחיר',
quantity: extractRoom.isNotEmpty ? extractRoom[0] : '0.0',
),
this will do the work

Flutter Bind Json data in ListView not showing in UI

My Json response status code is 200 and the object is also created but when I try to bind it with UI in ListView it doesn't show anything. I have also parsed created the model from the json data.
Here's my API_manager.dart file:
import 'package:http/http.dart' as http;
import 'package:aritic/models/contactsModel.dart';
// ignore: camel_case_types
class API_Manager {
Future<ContactsModel> getContacts() async {
var client = http.Client();
var contactsModel;
String contacts_url =
'https://exampleapi.com';
String basicAuth = 'Basic auth key example';
try {
var response = await client.get(contacts_url,
headers: <String, String>{'authorization': basicAuth});
print(response.statusCode);
if (response.statusCode == 200) {
var jsonString = response.body;
var jsonMap = json.decode(jsonString);
contactsModel = contactsModel.fromJson(jsonMap);
}
} catch (Exception) {
return contactsModel;
}
return contactsModel;
}
}
My UI code:
import 'package:aritic/models/contactsModel.dart';
import 'package:aritic/services/api_manager.dart';
class ContactsPage extends StatefulWidget {
#override
_ContactsPageState createState() => _ContactsPageState();
}
class _ContactsPageState extends State<ContactsPage>
with SingleTickerProviderStateMixin {
Future<ContactsModel> _contactsModel;
bool isSearching = false;
TabController _tabController;
#override
void initState() {
// TODO: implement initState
super.initState();
_tabController = TabController(length: 2, initialIndex: 0, vsync: this);
_tabController.addListener(_handleTabIndex);
}
#override
void dispose() {
_tabController.removeListener(_handleTabIndex);
_tabController.dispose();
super.dispose();
}
void _handleTabIndex() {
setState(() {});
}
#override
Widget build(BuildContext context) {
_contactsModel = API_Manager().getContacts();
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: Text('Contacts'),
bottom: PreferredSize(
child: Align(
alignment: Alignment.centerLeft,
child: TabBar(
controller: _tabController,
isScrollable: true,
unselectedLabelColor: Colors.white.withOpacity(0.3),
indicatorColor: Colors.white,
tabs: [
Tab(
child: Text('Contacts'),
),
Tab(
child: Text('Companies'),
)
],
),
),
preferredSize: Size.fromHeight(40.0)),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 16.0),
child: IconButton(
icon: Icon(Icons.search),
color: Colors.white,
onPressed: () {},
),
),
],
),
body: TabBarView(controller: _tabController, children: <Widget>[
Container(
height: double.infinity,
child: FutureBuilder<ContactsModel>(
future: _contactsModel,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
padding: const EdgeInsets.all(6),
itemCount: snapshot.data.contacts.length,
itemBuilder: (context, index) {
var contact = snapshot.data.contacts[index];
return Container(
height: 100,
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(contact.owner.username,
style: TextStyle(fontSize: 16))
],
),
);
});
} else
return Center(child: CircularProgressIndicator());
})),
Container(
height: double.infinity,
child: ListView(
padding: const EdgeInsets.all(6),
children: <Widget>[
InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => ViewCompany()));
},
child: Container(
height: 50,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Example company',
style: TextStyle(fontSize: 16),
),
Text(
'Example company',
style: TextStyle(fontSize: 14),
)
],
),
),
),
SizedBox(
height: 5,
),
InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => ViewCompany()));
},
child: Container(
height: 50,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'example',
style: TextStyle(fontSize: 16),
),
Text(
'example',
style: TextStyle(fontSize: 14),
)
],
),
),
),
],
)),
]),
floatingActionButton: _bottomButtons(),
));
}
Widget _bottomButtons() {
return _tabController.index == 0
? FloatingActionButton(
shape: StadiumBorder(),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return AddContacts();
}));
},
backgroundColor: Colors.cyan,
child: Icon(
Icons.person_add,
color: Colors.white,
))
: FloatingActionButton(
shape: StadiumBorder(),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return AddCompany();
}));
},
backgroundColor: Colors.cyan,
child: Icon(
Icons.add,
color: Colors.white,
),
);
}
}
Output Screen:
ListView should be displayed here
Dart DevTools network analysis:
response code is displayed
Json Viewer:
Contacts Json
Json sample(complete json too big to upload here):
{
"total": "187144",
"contacts": {
"897": {
"isPublished": true,
"id": 897,
"fields": {
"core": {
"points": {
"id": "47",
"label": "Points"
},
"firstname": {
"id": "2",
"label": "First Name",
"value": "Jason"
},
"lastname": {
"id": "3",
"label": "Last Name",
"value": "Lamuda"
},
"...": {
"..." : "..."
}
},
"ipAddresses": [
{
"ip": "70.127.91.131",
"ipDetails": {
"city": "Bradenton",
"region": "Florida",
"timezone": "America/New_York",
}
},
"...": {
"..." : "..."
}
The JSON has this:
{
"total": "187144",
"contacts": {
"897": {
"isPublished": true,
"id": 897,
"fields": {
So your ContactModel.contacts is a Map keyed by the id values "897" etc, not a List, so this line returns null:
var contact = snapshot.data.contacts[index];
(This should throw an exception when you reference the members of contact.) You can index into the Map like this:
List keys = snapshot.data.contacts.keys.toList();
List values = snapshot.data.contacts.values.toList();
return ListView.builder(
padding: const EdgeInsets.all(6),
itemCount: snapshot.data.contacts.length,
itemBuilder: (context, index) {
var contact = values[index];
BTW this line in API_Manager is strange:
contactsModel = contactsModel.fromJson(jsonMap);
It gives a Null pointer exception. It should of course be:
contactsModel = ContactsModel.fromJson(jsonMap);

JSON data from API call doesn't show in ListView FutureBuilder Flutter

My Json response status code is 200 and the object is also created but when I try to bind it with UI in ListView it doesn't show anything. I have used quicktype.io to parse my json data that I received from the API call.
Here's my API_manager.dart file:
import 'package:http/http.dart' as http;
import 'package:aritic/models/contactsModel.dart';
// ignore: camel_case_types
class API_Manager {
Future<ContactsModel> getContacts() async {
var client = http.Client();
var contactsModel;
String contacts_url =
'https://exampleapi.com';
String basicAuth = 'Basic auth key example';
try {
var response = await client.get(contacts_url,
headers: <String, String>{'authorization': basicAuth});
print(response.statusCode);
if (response.statusCode == 200) {
var jsonString = response.body;
var jsonMap = json.decode(jsonString);
contactsModel = contactsModel.fromJson(jsonMap);
}
} catch (Exception) {
return contactsModel;
}
return contactsModel;
}
}
My UI code:
import 'package:aritic/models/contactsModel.dart';
import 'package:aritic/services/api_manager.dart';
class ContactsPage extends StatefulWidget {
#override
_ContactsPageState createState() => _ContactsPageState();
}
class _ContactsPageState extends State<ContactsPage>
with SingleTickerProviderStateMixin {
Future<ContactsModel> _contactsModel;
bool isSearching = false;
TabController _tabController;
#override
void initState() {
// TODO: implement initState
super.initState();
_tabController = TabController(length: 2, initialIndex: 0, vsync: this);
_tabController.addListener(_handleTabIndex);
}
#override
void dispose() {
_tabController.removeListener(_handleTabIndex);
_tabController.dispose();
super.dispose();
}
void _handleTabIndex() {
setState(() {});
}
#override
Widget build(BuildContext context) {
_contactsModel = API_Manager().getContacts();
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: Text('Contacts'),
bottom: PreferredSize(
child: Align(
alignment: Alignment.centerLeft,
child: TabBar(
controller: _tabController,
isScrollable: true,
unselectedLabelColor: Colors.white.withOpacity(0.3),
indicatorColor: Colors.white,
tabs: [
Tab(
child: Text('Contacts'),
),
Tab(
child: Text('Companies'),
)
],
),
),
preferredSize: Size.fromHeight(40.0)),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 16.0),
child: IconButton(
icon: Icon(Icons.search),
color: Colors.white,
onPressed: () {},
),
),
],
),
body: TabBarView(controller: _tabController, children: <Widget>[
Container(
height: double.infinity,
child: FutureBuilder<ContactsModel>(
future: _contactsModel,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
padding: const EdgeInsets.all(6),
itemCount: snapshot.data.contacts.length,
itemBuilder: (context, index) {
var contact = snapshot.data.contacts[index];
return Container(
height: 100,
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(contact.owner.username,
style: TextStyle(fontSize: 16))
],
),
);
});
} else
return Center(child: CircularProgressIndicator());
})),
Container(
height: double.infinity,
child: ListView(
padding: const EdgeInsets.all(6),
children: <Widget>[
InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => ViewCompany()));
},
child: Container(
height: 50,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Example company',
style: TextStyle(fontSize: 16),
),
Text(
'Example company',
style: TextStyle(fontSize: 14),
)
],
),
),
),
SizedBox(
height: 5,
),
InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => ViewCompany()));
},
child: Container(
height: 50,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'example',
style: TextStyle(fontSize: 16),
),
Text(
'example',
style: TextStyle(fontSize: 14),
)
],
),
),
),
],
)),
]),
floatingActionButton: _bottomButtons(),
));
}
Widget _bottomButtons() {
return _tabController.index == 0
? FloatingActionButton(
shape: StadiumBorder(),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return AddContacts();
}));
},
backgroundColor: Colors.cyan,
child: Icon(
Icons.person_add,
color: Colors.white,
))
: FloatingActionButton(
shape: StadiumBorder(),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return AddCompany();
}));
},
backgroundColor: Colors.cyan,
child: Icon(
Icons.add,
color: Colors.white,
),
);
}
}
Created model(contactsModel.dart):
import 'dart:convert';
ContactsModel contactsModelFromJson(String str) => ContactsModel.fromJson(json.decode(str));
String contactsModelToJson(ContactsModel data) => json.encode(data.toJson());
class ContactsModel {
ContactsModel({
this.total,
this.contacts,
});
String total;
Map<String, Contact> contacts;
factory ContactsModel.fromJson(Map<String, dynamic> json) => ContactsModel(
total: json["total"],
contacts: Map.from(json["contacts"]).map((k, v) => MapEntry<String, Contact>(k, Contact.fromJson(v))),
);
Map<String, dynamic> toJson() => {
"total": total,
"contacts": Map.from(contacts).map((k, v) => MapEntry<String, dynamic>(k, v.toJson())),
};
}
class Contact {
Contact({
this.isPublished,
this.dateAdded,
this.dateModified,
this.createdBy,
this.createdByUser,
this.modifiedBy,
this.modifiedByUser,
this.id,
this.points,
this.color,
this.fields,
this.lastActive,
this.owner,
this.ipAddresses,
this.tags,
this.utmtags,
this.stage,
this.dateIdentified,
this.preferredProfileImage,
this.doNotContact,
this.frequencyRules,
});
bool isPublished;
DateTime dateAdded;
DateTime dateModified;
int createdBy;
String createdByUser;
int modifiedBy;
String modifiedByUser;
int id;
int points;
dynamic color;
Fields fields;
dynamic lastActive;
Owner owner;
List<dynamic> ipAddresses;
List<Tag> tags;
List<dynamic> utmtags;
Stage stage;
DateTime dateIdentified;
dynamic preferredProfileImage;
List<dynamic> doNotContact;
List<dynamic> frequencyRules;
factory Contact.fromJson(Map<String, dynamic> json) => Contact(
isPublished: json["isPublished"],
dateAdded: DateTime.parse(json["dateAdded"]),
dateModified: json["dateModified"] == null ? null : DateTime.parse(json["dateModified"]),
createdBy: json["createdBy"],
createdByUser: json["createdByUser"],
modifiedBy: json["modifiedBy"] == null ? null : json["modifiedBy"],
modifiedByUser: json["modifiedByUser"] == null ? null : json["modifiedByUser"],
id: json["id"],
points: json["points"],
color: json["color"],
fields: Fields.fromJson(json["fields"]),
lastActive: json["lastActive"],
owner: Owner.fromJson(json["owner"]),
ipAddresses: List<dynamic>.from(json["ipAddresses"].map((x) => x)),
tags: List<Tag>.from(json["tags"].map((x) => Tag.fromJson(x))),
utmtags: List<dynamic>.from(json["utmtags"].map((x) => x)),
stage: Stage.fromJson(json["stage"]),
dateIdentified: DateTime.parse(json["dateIdentified"]),
preferredProfileImage: json["preferredProfileImage"],
doNotContact: List<dynamic>.from(json["doNotContact"].map((x) => x)),
frequencyRules: List<dynamic>.from(json["frequencyRules"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"isPublished": isPublished,
"dateAdded": dateAdded.toIso8601String(),
"dateModified": dateModified == null ? null : dateModified.toIso8601String(),
"createdBy": createdBy,
"createdByUser": createdByUser,
"modifiedBy": modifiedBy == null ? null : modifiedBy,
"modifiedByUser": modifiedByUser == null ? null : modifiedByUser,
"id": id,
"points": points,
"color": color,
"fields": fields.toJson(),
"lastActive": lastActive,
"owner": owner.toJson(),
"ipAddresses": List<dynamic>.from(ipAddresses.map((x) => x)),
"tags": List<dynamic>.from(tags.map((x) => x.toJson())),
"utmtags": List<dynamic>.from(utmtags.map((x) => x)),
"stage": stage.toJson(),
"dateIdentified": dateIdentified.toIso8601String(),
"preferredProfileImage": preferredProfileImage,
"doNotContact": List<dynamic>.from(doNotContact.map((x) => x)),
"frequencyRules": List<dynamic>.from(frequencyRules.map((x) => x)),
};
}
class ......{}
Output Screen: here
Json Viewer: here
Dart Devtools: here
This is probably not a problem with your json parsing, but a UI issue. Putting Columns or Rows inside ListViews or the opposite. If there was something wrong with the json, you'd be seeing the return Center(child: CircularProgressIndicator());,
But instead, you're getting an empty UI.
Check your debug console, if you have RenderView errors, or failed to layout render-box issues, this will be the cause of them.
Try using the property of shrink wrap in your lists:
ListView(shrinkwrap:true...
and
ListView.builder(shirinkrap:true...
Also, wrap your Row that inside the ListView with a LimitedBox
i.e
LimitedBox(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [

How to update data in mysql by flutter

I try to edit data in mysql from flutter. I send Id from page one to page two And by id I Inquire about specific data then edit it With the condition where Id=Id. Now when the application works, I can make sure Id send to php file. I try here to update field of name.
Logcat
I/flutter: tappedddd http://xxxxxxxxx/ccv.php?id=66
I can see ID is sent with the link but data now do not change in the database.I don't know what is problem. Anyone know solution for this problem?
my full code:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'dart:convert';
import 'MyPreferences.dart';
class Update extends StatefulWidget {
var getid;
Update({Key key, this.getid}) : super(key: key);
#override
_UpdateState createState() => new _UpdateState();
}
class _UpdateState extends State<Update> {
MyPreferences _myPreferences = MyPreferences();
var getid;
var _isLoading = false;
var data;
var _username = "";
var _phone = "";
var _password = "";
var image ="";
var _phoneController = new TextEditingController();
var _firstnameController = new TextEditingController();
var _lastnameController = new TextEditingController();
Future<String> _ShowDialog(String msg) async {
return showDialog<String>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return new AlertDialog(
title: new Text('Rewind and remember'),
content: new SingleChildScrollView(
child: new ListBody(
children: <Widget>[
new Text(msg),
],
),
),
actions: <Widget>[
new FlatButton(
child: new Text('Close'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
void _editData() async {
var url = "http://xxxxxxxx/ccv.php?id=${widget.getid}";
print("tappedddd $url");
var response = await http.post(url, body: {
"id": widget.getid,
// "id": _userController.text,
"name": _firstnameController.text,
// "name": _phoneController.text,
// "name": _lastnameController.text,
});
if (response.statusCode == 200) {
_ShowDialog("Updated Successfully");
} else {
_ShowDialog("Updated Failer");
}
//onEditedAccount();
//print(_adresseController.text);
}
_fetchData() async {
final url =
"http://xxxxxxxxxx/nhy.php?id=${widget.getid}";
final response = await http.get(url);
if (response.statusCode == 200) {
final map = json.decode(response.body);
final videosMap = map["result"];
setState(() {
_isLoading = true;
this.data = videosMap;
_username = data[0]['name'];
image = data[0]['image'];
print(data);
});
}
}
#override
void initState() {
super.initState();
_fetchData();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text("Update Profile"),
),
body: new Center(
child: data == null
? new CircularProgressIndicator()
: new ListView(
children: <Widget>[
new Padding(
padding: const EdgeInsets.fromLTRB(5, 100, 5, 5),
child: Column(
children: <Widget>[
new Padding(
padding:
const EdgeInsets.only(top: 20.0, bottom: 25.0),
child: Expanded(flex: 1,
child: Container(
child: Card(
child: new Padding(
padding: const EdgeInsets.all(5.0),
child: Image.network(
image,
width: 300,
height: 300,
fit: BoxFit.cover,
),
),
),
),
),
),
Card (
child: Column(
children: <Widget>[
SizedBox(
height: 10.0,
),
Container(
margin: EdgeInsets.all(4),
child: TextField(
maxLength: 10,
decoration: InputDecoration(
labelText: ("name : "),
filled: true,
hintText: _username),
controller: _firstnameController,
),
),
SizedBox(
height: 5.0,
),
Container(
margin: EdgeInsets.all(4),
child: TextField(
maxLength: 8,
decoration: InputDecoration(
labelText: ("phone : "),
filled: true,
hintText: _phone),
controller: _phoneController,
),
),
SizedBox(
height: 5.0,
),
Container(
margin: EdgeInsets.all(4),
child: TextField(
maxLength: 8,
decoration: InputDecoration(
labelText: ("password : "),
filled: true,
hintText: _password),
controller: _lastnameController,
),
),
SizedBox(
height: 5.0,
),
]
)
),
SizedBox(
width: double.infinity,
child: new FlatButton(
child: const Text('Update'),color: Colors.amber,
padding: EdgeInsets.fromLTRB(100, 18, 100, 18),
onPressed: () { _editData();
},
),
),
SizedBox(
height: 10.0,
),
],
),
)
],
),
));
}
}
php file:
<?php
require_once 'connt.php';
$id=$_POST['id'];
$name =$_POST['name'];
$query="UPDATE topics SET name='$name' WHERE id='$id'";
$exeQuery = mysqli_query($con, $query) ;
if($exeQuery){
echo (json_encode(array('code' =>1, 'message' => 'Modifier avec succee')));
}else {echo(json_encode(array('code' =>2, 'message' => 'Modification Non Terminer')));
}
?>

Flutter - "Range error (length)" when trying to parse local json data

I have a JSON file that has a text and each sentence is in a separate JSON object, the user shoud be able to navigate between sentenes with next() and previous() but when the app loads I get this error:
RangeError (index): Invalid value: Valid value range is empty: 0
until I press any other button on the screen that's when the text loads and get displayed.
The card itself is a statefulWidget and here's my code:
class _BottomCardsState extends State<BottomCards>{
bool isLoadingEnded = false;
Future<Null> getAllData() async{
await DefaultAssetBundle.of(context).loadString('assets/json/data.json').then((response){
isLoadingEnded = true;
var decodedData = json.decode(response);
for(Map d in decodedData){
dataList.add(Data.fromJson(d));
}
});
}
#override
void initState() {
super.initState();
getAllData();
}
int dataIndex = 0;
#override
Widget build(BuildContext context) {
int myNbr = dataList[dataIndex].id;
return Container(
child: Material(
color: Colors.transparent,
child: Card(
margin: EdgeInsets.symmetric(horizontal: 10.0),
elevation: 6.0,
child: Container(
alignment: Alignment.topCenter,
padding: EdgeInsets.symmetric(horizontal: 12.0,),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
IconButton(
splashColor: gradientStart,
icon: Icon(Icons.keyboard_arrow_left,),
onPressed: () {_previous();},
),
IconButton(
splashColor: gradientStart,
icon: Icon(Icons.keyboard_arrow_right,),
onPressed: () {_next();},
),
],
),
SizedBox(height: 4.0,),
isLoadingEnded == true ? Container(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: InkWell(
splashColor: Colors.lightBlue[100],
onTap: (){},
//the paragraph gets displayed here
child: Text(dataList[dataIndex].paragraph,
),
),
],
),
SizedBox(height: 8.0,),
Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Chip(
backgroundColor: secondaryDark,
label: Text('Number: $myNbr',
style: TextStyle(color: Colors.white, fontSize: 10.0, fontWeight: FontWeight.w500),),
),
],
),
],
),
): Center(child: loadingIndicator(),),
SizedBox(height: 6.0),
],
),
),
),
),
);
}
}
`
My JSON format:
{
"id": 1,
"paragraph": "lorem ipsum"
},
...
You need to wait until data is filled up.
change your getAllData method. Like,
Future<List<Data>> getAllData() async{
var response = await DefaultAssetBundle.of(context).loadString('assets/json/data.json')
var decodedData = json.decode(response);
for(Map d in decodedData){
dataList.add(Data.fromJson(d));
}
return dataList;
}
and now wait on build method. Like,
#override
Widget build(BuildContext context) {
return FutureBuilder<List<Data>>(
future: getAllData(),
builder: (context, snapshot) {
if (snapshot.hasData) {
print("Here you can get data "+snapshot.data.toString());
//you can put your ui here
} else {
print("Waiting mode");
return Container(
color: Colors.blue,
);
}
},
)
}
import 'package:flutter/services.dart' show rootBundle;
the first of fall your data is like a map, and you are trying to store in a list. as I can see your data is the type of map.
{
"id": 1,
"paragraph": "lorem ipsum"
}
Future<void> getAllData() async {
final res= await rootBundle.loadString('assets/config.json');
final json = jsonDecode(res.body);
var parse = json as Map;
Data data=Data.fromJson(parse);
}
and if JSON is contained list data then
[
{
"id": 1,
"paragraph": "lorem ipsum"
},
{
"id": 1,
"paragraph": "lorem ipsum"
}
]
then
Future<void> getAllData() async {
final res= await rootBundle.loadString('assets/config.json');
final json = jsonDecode(res.body);
var parse = json as List;
parse.forEach((d){
dataList.add(Data.fromJson(d));
});
}