How to use ListString in groupBy ? with flutter - flutter

Hello I try to display a list of data grouped by date.
First I load all key/value saved with sharedpreference
after I use regex to match for each date the data key and data value
after I use List to add all date/data/value like that :
List<String> MylistString=[{"release_date":"2020-10-30","note3":"2222222"}, {"release_date":"2020-10-29","note3":"1111111"}, {"release_date":"2020-10-31","note3":"3333333"}, {"release_date":"2020-10-29","note4":"bdlbd"}]
I don't successed to use groupBy with a MyListString even after add .toString
var foo = groupBy({MylistString.toString()}, (i) => i["release_date"]);
But If I create a static String with the same data it work
Here is complet code who display a list of key value for each date, I search to group this data by date:
import 'package:flutter/material.dart';
import 'package:flutter_timeline/flutter_timeline.dart';
import 'package:flutter_timeline/indicator_position.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:intl/intl.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
void main() {
runApp(TimelineDemoApp());
}
class TimelineDemoApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Timeline',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: PlainTimelineDemoScreen(),
);
}
}
class PlainTimelineDemoScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() => _PlainTimelineDemoScreenState();
}
class _PlainTimelineDemoScreenState extends State<PlainTimelineDemoScreen> {
List<EventData> eventsData;
List<TimelineEventDisplay> events;
String Data1;
String Data2;
#override
void initState() {
super.initState();
}
List<String> stringList_note_formatted = [];
List<String> stringList_date_note1 =[] ;
String value_note1;
List<String> stringList_date_note2 =[] ;
String value_note2;
load_data() async {
//---------------------------------------------------------------------------------------------------
var input = '"2020-10-30","note1":"value1","2020-10-30","note2":"value2","2020-10-31","note1":"value3","2020-10-32","note2":"value4",';
var inputItarable = input.split(',').where((s) => s.isNotEmpty);
var i = inputItarable.iterator;
var tmp = {};
while (i.moveNext()) {
var key = i.current; i.moveNext();
var value = i.current.split(':'); (tmp[key] ??= []).add(value); } print(tmp);
var output = tmp.keys.map((key) {
var map = {}; map['"release_date"'] = key; tmp[key].forEach((e) => map[e[0]] = e[1]);
return map; }).toList();
print(output);
if (output == null) {
//no data available
eventsData = [];
} else {
//deserialize event data from json
var items = jsonDecode(output) as List;
eventsData = items.map((i) => EventData.fromJson(i)).toList();
}
//render event data
events = eventsData.map(plainEventDisplay).toList();
}
final myController2 = TextEditingController();
final myController3 = TextEditingController();
String note2;
dialog_text() async{
await showDialog<String>(
barrierDismissible: false, // user must tap button!
context: context,
builder: (BuildContext context){
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))),
title: Text(("Write something"),textAlign: TextAlign.center, style: TextStyle(color: Colors.black, fontWeight: FontWeight.w600, fontSize: 20)),
content:
Container(
width: MediaQuery.of(context).size.width*1,
child:
new ListView(
children: <Widget>[
Card(
color: Colors.grey[200],
child: Padding(
padding: EdgeInsets.all(8.0),
child: TextField(
controller: myController2,
maxLines:2,
decoration: InputDecoration.collapsed(hintText: "Your text"),
),
)
),
],
),
),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.pop(context,);
},
child: Text('Validate', textAlign:TextAlign.center,style: TextStyle(
fontWeight: FontWeight.bold,
fontSize:15),
),
),
],
);
}
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Timeline test"),
),
body: FutureBuilder(
future: load_data(),
builder: (context, snapshot) {
return _buildTimeline();
},
),
);
}
TimelineEventDisplay plainEventDisplay(EventData eventData) {
var formattedTime = DateFormat('dd-MM-yyyy').format(eventData.dateTime);
Widget text1() {
if (eventData.data1==null){
return Container();
}else{
return Text("note1 : ${eventData.data1}");
}
}
Widget text2() {
if (eventData.data2==null){
return Container();
}else{
return Text("note2 : ${eventData.data2}");
}
}
return TimelineEventDisplay(
anchor: IndicatorPosition.top,
indicatorOffset: Offset(0, 0),
child: TimelineEventCard(
title: Text("${formattedTime}"),
content: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new Row(
children: [
new Expanded(
child : new Card(
elevation: 3,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
child: new Container(
padding: const EdgeInsets.all (10.0),
child: Column(
children: [
text1(),
Padding(
padding: EdgeInsets.all(5.0),),
text2(),
],
),
),
)
)
],
)
],
)),
indicator: TimelineDots.of(context).circleIcon,
);
}
Widget _buildTimeline() {
return TimelineTheme(
data: TimelineThemeData(
lineColor: Colors.blueAccent, itemGap: 5, lineGap: 0),
child: Timeline(
anchor: IndicatorPosition.center,
indicatorSize: 56,
altOffset: Offset(10, 10),
events: events,
));
}
}
class EventData {
final DateTime dateTime;
final String data1;
final String data2;
EventData(this.dateTime, this.data1, this.data2);
EventData.fromJson(Map<String, dynamic> json)
: dateTime = DateTime.parse(json['release_date']),
data1 = json['note1'],
data2 = json['note2'];
Map<String, dynamic> toJson() => {
'release_date': dateTime.toIso8601String(),
'note1': data1,
'note2': data2,
};
}

Related

local state variable not updating

For some weird reason, my local state variable "_jobApplicationState" is not updating.
I see that it is updated in the database, but its not updating on my page.
If I leave the record and come back, everything works as expected.
I am driving this functionality by pressing the button 'Send inquiry'.
I took out a bunch of code to make it easy to read.
I got this to work for a minute at somepoint. but I forgot to save:(
class JobApplicationView extends StatefulWidget {
const JobApplicationView({Key? key}) : super(key: key);
#override
_JobApplicationViewState createState() => _JobApplicationViewState();
}
// https://youtu.be/VPvVD8t02U8?t=90350
class _JobApplicationViewState extends State<JobApplicationView> {
CloudJobApplication? _jobApplication;
final _formKey = GlobalKey<FormState>();
final currentUser = AuthService.firebase().currentUser!;
late final FirebaseCloudStorage _firebaseService;
//
late String _jobApplicationState;
//
late DateTime _jobApplicationStartDate;
late DateTime _jobApplicationEndDate;
//
bool? isJobCreatorSameAsJobApplicator;
String? _jobCreatorId;
String? _jobApplicatorId;
String? _jobDescription;
List? _jobUserData;
String? _jobAddress;
String? _jobType;
//
#override
void initState() {
super.initState();
_jobApplicationStartDate = DateTime.now();
_jobApplicationEndDate = DateTime.now();
_firebaseService = FirebaseCloudStorage();
// _jobDescriptionController = TextEditingController();
// _jobAreaCodeController = TextEditingController();
// _jobApplicationStateController = TextEditingController();
}
//Future<CloudJobApplication>
createOrGetExistingJob(BuildContext context) async {
final widgetJobApplication = context.getArgument<CloudJobApplication>();
if (widgetJobApplication != null) {
_jobApplication = widgetJobApplication;
_jobApplicationState = widgetJobApplication.jobApplicationState;
_jobApplicatorId = widgetJobApplication.jobApplicatorId;
_jobCreatorId = widgetJobApplication.jobCreatorId;
_jobDescription = widgetJobApplication.jobApplicationDescription;
return widgetJobApplication;
}
print('ELSE TRIGGERED!');
return widgetJobApplication;
}
void _updateJobField(localStateField, jobColumn, jobColumnValue) async {
//* localStateField: local field to update so that the build context is refreshed
//* jobColumn: the name of the column in the db
//* jobColumnValue: the value for the jobColumn
setState(() {
if (localStateField == '_jobApplicationState') {
_jobApplicationState = jobColumnValue;
}
});
await _firebaseService.updateJobApplicationColumn(
documentId: _jobApplication?.documentId as String,
fieldNameColumn: jobColumn,
fieldNameColumnValue: jobColumnValue,
);
}
sendInqury() {
print('setting job applications state!');
print('_jobApplicationState b4:: $_jobApplicationState');
_updateJobField(_jobApplicationState, jobApplicationStateColumn,
jobApplicationStateOpen);
print('_jobApplicationState after:: $_jobApplicationState');
}
#override
void dispose() {
//_deleteJobIfTextIsEmpty();
// _jobDescriptionController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('update job application'),
actions: [],
),
body: FutureBuilder(
future: createOrGetExistingJob(context),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.done:
return Form(
key: _formKey,
child: ListView(
padding: const EdgeInsets.all(32.0),
children: [
//getStateChevrons(_jobApplicationState),
const Divider(
height: 20,
thickness: 5,
indent: 0,
endIndent: 0,
color: Colors.blue,
),
Text(_jobApplicationState),
TextButton(
style: TextButton.styleFrom(
foregroundColor: Colors.white,
backgroundColor: Colors.blue,
padding: const EdgeInsets.all(16.0),
textStyle: const TextStyle(fontSize: 20),
),
onPressed: sendInqury,
child: const Text('Send inquiry'),
)
],
),
);
default:
return const CircularProgressIndicator();
}
},
),
);
}
}
I figured out the answer, here is the answer code:
import 'dart:developer';
import 'package:flutter/material.dart';
import '../../services/cloud/cloud_job_application.dart';
import '/services/auth/auth_service.dart';
import '/utilities/generics/get_arguments.dart';
import '/services/cloud/firebase_cloud_storage.dart';
class JobApplicationView extends StatefulWidget {
const JobApplicationView({Key? key}) : super(key: key);
#override
_JobApplicationViewState createState() => _JobApplicationViewState();
}
// https://youtu.be/VPvVD8t02U8?t=90350
class _JobApplicationViewState extends State<JobApplicationView> {
CloudJobApplication? _jobApplication;
late final FirebaseCloudStorage cloudFunctions;
final _formKey = GlobalKey<FormState>();
final currentUser = AuthService.firebase().currentUser!;
// state varibles
String _jobApplicationState = 'default';
String _jobApplicationSubState = 'default';
late final TextEditingController _jobDescriptionController;
#override
void initState() {
super.initState();
cloudFunctions = FirebaseCloudStorage();
_jobDescriptionController = TextEditingController();
}
//Future<CloudJobApplication>
getExistingJobApplication(BuildContext context) async {
log('getExistingJobApplication()');
if (_jobApplicationState == 'default') {
var widgetJobApplication = context.getArgument<CloudJobApplication>();
log('first time openning job application, returning server data');
_jobApplication = widgetJobApplication;
_jobApplicationState =
widgetJobApplication?.jobApplicationState as String;
_jobDescriptionController.text =
widgetJobApplication?.jobApplicationDescription as String;
return widgetJobApplication;
} else {
log('job application has been updated, returnnig local data');
return cloudFunctions.getJobApplication(_jobApplication!.documentId);
}
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('update job application'),
actions: [],
),
body: FutureBuilder(
future: getExistingJobApplication(context),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.done:
return Form(
key: _formKey,
child: ListView(padding: const EdgeInsets.all(32.0), children: [
Text(_jobApplicationState),
Text(_jobDescriptionController.text),
const Divider(
height: 20,
thickness: 5,
indent: 0,
endIndent: 0,
color: Colors.blue,
),
TextFormField(
controller: _jobDescriptionController,
maxLines: 5,
decoration: InputDecoration(
// enabled: _jobState == jobStateNew ? true : false,
hintText: "The toilet wont flush",
filled: true,
// fillColor: _jobState == jobStateNew ? Colors.white : Colors.grey,
label: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.0),
color: Colors.white,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: const [
Padding(padding: EdgeInsets.only(left: 8.0)),
Icon(Icons.info_outline),
Padding(
padding: EdgeInsets.only(left: 8.0, right: 8.0),
child: Text("Job description"),
),
],
),
),
),
validator: (str) =>
str == '' ? "Job description can't be empty" : null,
),
TextButton(
onPressed: () async {
setState(() {
_jobApplicationState = 'Open';
});
await cloudFunctions.updateJobApplication(
documentId: _jobApplication?.documentId as String,
jobDescription: _jobDescriptionController.text,
jobApplicationState: 'Open',
);
},
child: const Text('update state')),
//
]),
);
default:
return const CircularProgressIndicator();
}
},
),
);
}
}
You should separate the UI and logic -> create a jobApplication Model.
Pack all your logic into a ChangeNotifier and notifyListeners on change.
This is also better for performance because it only rebuilds needed parts of the UI.
I can recommend using a ChangeNotifierProvider.
class JobApplicationProvider extends ChangeNotifier {
JobApplication jobapplication = BasicParam.standard;
void setJobApplication(json) async {
jobapplication = JobApplication.fromJson(json);
notifyListeners();
}
}
And in the build Method use it like this:
Widget build(BuildContext context) {
JobApplicationProvider jobApplication= Provider.of(context);
return Text(jobApplication.state);
}

Duplicate GlobalKey detected in tree widget scaffoldState

I was trying to update data (add, edit, delete) from my list using API, when I clicked something to update the list e.g deleting an item it showed a successfully updated. but in the Debug Console, there's an error that says
The following assertion was thrown while finalizing the widget tree:
Duplicate GlobalKey detected in the widget tree. The following GlobalKey
was specified multiple times in the widget tree. This will lead to
parts of the widget tree being truncated unexpectedly, because the
second time a key is seen, the previous instance is moved to the new
location. The key was:
[LabeledGlobalKey #47c37] This was determined by noticing that after the widget with the above global key was moved out
of its previous parent, that previous parent never updated during this
frame, meaning that it either did not update at all or updated before
the widget was moved, in either case implying that it still thinks
that it should have a child with that global key.
And when I tried going back to the Previous screen it just showed Blank Screen
Here's the code
Model
import 'dart:convert';
class Nasabah {
int id;
String nama_debitur;
String alamat;
String no_telp;
String no_ktp;
String no_selular;
Nasabah({
this.id = 0,
this.nama_debitur,
this.alamat,
this.no_telp,
this.no_ktp,
this.no_selular,
});
factory Nasabah.fromJson(Map<String, dynamic> json) => Nasabah(
id: json["id"],
nama_debitur: json["nama_debitur"],
alamat: json["alamat"],
no_telp: json["no_telp"],
no_ktp: json["no_ktp"],
no_selular: json["no_selular"],
);
factory Nasabah.fromMap(Map<String, dynamic> map) => Nasabah(
id: map["id"],
nama_debitur: map["nama_debitur"],
alamat: map["alamat"],
no_telp: map["no_telp"],
no_ktp: map["no_ktp"],
no_selular: map["no_selular"],
);
Map<String, dynamic> toJson() => {
"id": id,
"nama_debitur": nama_debitur,
"alamat": alamat,
"no_telp": no_telp,
"no_ktp": no_ktp,
"no_selular": no_selular,
};
#override
String toString() {
return 'Nasabah{id: $id, nama_debitur: $nama_debitur, alamat: $alamat, no_telp: $no_telp, no_ktp: $no_ktp, no_selular: $no_selular}';
}
}
class NasabahResult {
String status;
List<Nasabah> data = new List<Nasabah>();
NasabahResult({
this.status,
this.data,
});
factory NasabahResult.fromJson(Map<String, dynamic> data) => NasabahResult(
status: data["status"],
data: List<Nasabah>.from(
data["data"].map((item) => Nasabah.fromJson(item))),
);
}
NasabahResult nasabahResultFromJson(String jsonData) {
final data = json.decode(jsonData);
return NasabahResult.fromJson(data);
}
String nasabahToJson(Nasabah nasabah) {
final jsonData = nasabah.toJson();
return json.encode(jsonData);
}
Service
import 'package:flutter_auth/Models/nasabah.dart';
import 'dart:convert';
import 'package:http/http.dart' show Client;
class ApiService {
final String baseUrl = '192.168.100.242:8080';
Client client = Client();
Future<List<Nasabah>> getNasabah() async {
final response = await client.get('http://$baseUrl/api/mstdebitur');
print(response.body);
if (response.statusCode == 200) {
final nasabah = (json.decode(response.body) as List)
.map((e) => Nasabah.fromMap(e))
.toList();
return nasabah;
} else {
throw Exception('Failed to load post');
}
}
Future<bool> createNasabah(Nasabah data) async {
String url = new Uri.http("$baseUrl", "/api/mstdebitur/").toString();
final response = await client.post(url,
headers: {"Content-Type": "application/json"},
body: nasabahToJson(data));
if (response.statusCode == 201) {
return true;
} else {
return false;
}
}
Future<bool> updateNasabah(Nasabah data) async {
String url =
new Uri.http("$baseUrl", "/api/mstdebitur/${data.id}").toString();
final response = await client.put(url,
headers: {"Content-Type": "application/json"},
body: nasabahToJson(data));
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
Future<bool> deleteNasabah(int id) async {
String url = new Uri.http("$baseUrl", "/api/mstdebitur/$id").toString();
final response = await client.delete(url);
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
}
Home
import 'package:flutter/material.dart';
import 'package:flutter_auth/Models/nasabah.dart';
import 'package:flutter_auth/network/nasabah_service.dart';
import 'FormAddNasabah.dart';
import 'ListNasabah.dart';
GlobalKey<ScaffoldState> _scaffoldState = GlobalKey<ScaffoldState>();
// ignore: must_be_immutable
class DataNasabah extends StatefulWidget {
DataNasabah({Key key}) : super(key: key);
String title;
#override
_DataNasabahState createState() => _DataNasabahState();
}
class _DataNasabahState extends State<DataNasabah> {
ApiService apiService;
ListNasabah _listNasabah;
List<Nasabah> data;
#override
void initState() {
super.initState();
apiService = ApiService();
_listNasabah = new ListNasabah(apiService: apiService);
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldState,
appBar: AppBar(
title: Text(
'Data Nasabah',
style: TextStyle(color: Colors.white),
),
actions: <Widget>[
GestureDetector(
onTap: () async {
var result = await Navigator.push(
_scaffoldState.currentContext,
MaterialPageRoute(builder: (BuildContext context) {
return FormAddNasabah(nasabah: null);
}),
);
if (result != null) {
setState(() {});
}
},
child: Padding(
padding: const EdgeInsets.only(right: 16.0),
child: Icon(
Icons.add,
color: Colors.white,
),
),
)
],
),
body: _listNasabah.createViewList(),
);
}
}
List
import 'package:flutter/material.dart';
import 'package:flutter_auth/Models/nasabah.dart';
import 'package:flutter_auth/network/nasabah_service.dart';
import 'package:flutter_auth/screens/Menu/DataNasabah/FormAddNasabah.dart';
import 'package:flutter_auth/screens/Menu/DataNasabah/NasabahHome.dart';
import 'package:rflutter_alert/rflutter_alert.dart';
class ListNasabah {
ApiService apiService;
ListNasabah({this.apiService});
Widget createViewList() {
return SafeArea(
child: FutureBuilder(
future: apiService.getNasabah(),
builder: (BuildContext context, AsyncSnapshot<List<Nasabah>> snapshot) {
if (snapshot.hasError) {
return Center(
child: Text(
'Something wrong with message: ${snapshot.error.toString()}',
textAlign: TextAlign.center,
),
);
} else if (snapshot.connectionState == ConnectionState.done) {
List<Nasabah> nasabah = snapshot.data;
return nasabahListView(nasabah);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
Widget nasabahListView(List<Nasabah> listnasabah) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (context, index) {
Nasabah nasabah = listnasabah[index];
return Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
nasabah.nama_debitur,
style: Theme.of(context).textTheme.bodyText1,
),
Text(nasabah.alamat),
Text(nasabah.no_ktp),
Text(nasabah.no_telp),
Text(nasabah.no_selular),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FlatButton(
onPressed: () {
apiService.deleteNasabah(nasabah.id).then((value) =>
Navigator.of(context).pushNamed('start'));
},
child: Text(
"Hapus",
style: TextStyle(color: Colors.red),
),
),
FlatButton(
onPressed: () async {
var result = await Navigator.push(context,
MaterialPageRoute(builder: (context) {
return FormAddNasabah(
nasabah: nasabah,
);
}));
},
child: Text(
'Edit',
style: TextStyle(color: Colors.blue),
),
),
],
)
],
),
),
),
);
},
itemCount: listnasabah.length,
),
);
}
}
Form
import 'package:flutter/material.dart';
import 'package:flutter_auth/Models/nasabah.dart';
import 'package:flutter_auth/network/nasabah_service.dart';
import 'package:flutter_auth/screens/Menu/DataNasabah/NasabahHome.dart';
import 'package:rflutter_alert/rflutter_alert.dart';
class FormAddNasabah extends StatefulWidget {
Nasabah nasabah;
FormAddNasabah({this.nasabah});
#override
_FormAddNasabahState createState() => _FormAddNasabahState();
}
class _FormAddNasabahState extends State<FormAddNasabah> {
ApiService apiService;
TextEditingController _contNama = TextEditingController();
TextEditingController _contAlamat = TextEditingController();
TextEditingController _contNoTelp = TextEditingController();
TextEditingController _contNoKtp = TextEditingController();
TextEditingController _contNoSelular = TextEditingController();
#override
void initState() {
super.initState();
apiService = ApiService();
if (widget.nasabah != null) {
_contNama.text = widget.nasabah.nama_debitur;
_contAlamat.text = widget.nasabah.alamat;
_contNoTelp.text = widget.nasabah.no_telp;
_contNoKtp.text = widget.nasabah.no_ktp;
_contNoSelular.text = widget.nasabah.no_selular;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(color: Colors.white),
title: Text(
widget.nasabah == null ? "Tambah Nasabah" : "Edit Nasabah",
style: TextStyle(color: Colors.white),
),
),
body: Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
_buildTextField(_contNama, "Nama Nasabah"),
_buildTextField(_contAlamat, "Alamat"),
_buildTextField(_contNoTelp, "No Telp"),
_buildTextField(_contNoKtp, "No KTP"),
_buildTextField(_contNoSelular, "No Selular"),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: RaisedButton(
child: Text(widget.nasabah == null ? "Tambah" : "Edit"),
color: Colors.blue,
onPressed: () {
int id = 0;
if (widget.nasabah != null) {
id = widget.nasabah.id;
}
Nasabah nasabah = Nasabah(
id: id,
nama_debitur: _contNama.text,
alamat: _contAlamat.text,
no_telp: _contNoTelp.text,
no_ktp: _contNoKtp.text,
no_selular: _contNoSelular.text);
if (widget.nasabah == null) {
apiService.createNasabah(nasabah);
} else {
apiService.updateNasabah(nasabah);
}
Navigator.of(context)
.pushNamed('start')
.whenComplete(() => Navigator.pop(context));
},
),
)
],
),
)
],
),
);
}
Widget _buildTextField(TextEditingController _cont, String label) {
return TextField(
controller: _cont,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: label,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
}
}
Thank you for your attention!

Flutter: The value passed in parameter is null on the second page the first time

Flutter: The value passed in parameter is null on the second page the first time. if I do a hot reload, this value is not null.
maybe it's because of the TabBar but how do you get the real value for the first time while using TabBar?
Please help me find a solution to my problem
First page. And idBou is not null here
class BoutiquePage extends StatefulWidget {
int idboutique;
BoutiquePage({this.idboutique});
#override
_BoutiquePageState createState() => _BoutiquePageState();
}
class _BoutiquePageState extends State<BoutiquePage> {
SharedPreferences sharedPreferences;
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
String idBou ;
String nomAbon ;
String prenomAbon ;
String telAbon ;
String addAbon;
String nomBou;
String ville;
String pays;
String lien_photo_bout;
bool _isLoading = false;
String _errorText;
get article_afficher333 => article_afficher333;
#override
void initState() {
setState((){
getShaerInstance();
});
super.initState();
}
getShaerInstance() async {
sharedPreferences = await SharedPreferences.getInstance();
}
Future<Map<String, dynamic>> getAllStoreInfoData2(int idboutique) async {
final response = await http.get(http://xxxxxx.com+"boutique/home?id_bout="+idboutique.toString());
if (response.statusCode == 200) {
final jsonResponse = json.decode(response.body);
BoutiqueData myData = new BoutiqueData.fromJson(jsonResponse);
Map<String, dynamic> boutiqueinfodata = Map();
boutiqueinfodata["boutiqueType"] = myData.v_boutique.typeBoutique;
return boutiqueinfodata;
} else {
throw Exception("Failed to load Data");
}
}
//SharedPreferences
#override
Widget build(BuildContext context) {
Widget myboutiqueinfodata = FutureBuilder(
future: getAllStoreInfoData2(widget.idboutique),
builder: (context, snapshot) {
if (snapshot.hasData) {
Map<String, dynamic> alldata = snapshot.data;
typeBoutique = alldata["boutiqueType"];
List<ListeInfoBoutique> boutiqueInfoData = alldata["boutiqueInfoData"];
for (var i = 0; i < boutiqueInfoData.length; i++) {
idBou = boutiqueInfoData[i].idBou;
nomAbon = boutiqueInfoData[i].nomAbon;
prenomAbon = boutiqueInfoData[i].prenomAbon;
telAbon = boutiqueInfoData[i].telAbon;
addAbon = boutiqueInfoData[i].addAbon;
}
return Scaffold(
body: ListView(
children: <Widget>[
],
),
);
}else if (snapshot.hasError) {
return Container(
child: Center(
child: Text(AppLocalizations.of(context)
.translate('_MSG_ER_CONNEXION_CHARGE_DATA'),
style: TextStyle(
fontSize: 18,
fontFamily: 'Questrial'
),),
),
);
}
return new Center(
child: CircularProgressIndicator(),
);
});
return DefaultTabController(
length: 5,
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text(AppLocalizations.of(context)
.translate('_MY_STORE'), style: TextStyle(color: Colors.white, fontFamily: "Questrial"),),
iconTheme: new IconThemeData(color: Color(0xFFFFFFFF)),
actions: <Widget>[
//
],
bottom: TabBar(
isScrollable: true,
indicatorColor: Colors.white,
indicatorWeight: 5.0,
//onTap: (){},
tabs: <Widget>[
Tab(
child: Container(
child: Text(AppLocalizations.of(context)
.translate('_STORE_INFO'), style: TextStyle(color: Colors.white, fontSize: 18.0, fontFamily: 'Questrial'),),
),
),
Tab(
child: Container(
child: Text(AppLocalizations.of(context)
.translate('_MY_ARTICLES'), style: TextStyle(color: Colors.white, fontSize: 18.0, fontFamily: 'Questrial'),),
),
),
],
),
),
body: TabBarView(
children: <Widget>[
myboutiqueinfodata,
MesArticles(idboutique: idBou),
],
),
),
);
}
}
Secode page who print null a first time and after hot reload become not null
class MesArticles extends StatefulWidget {
final String idboutique;
const MesArticles({Key key, this.idboutique}) : super(key: key);
#override
_MesArticleState createState() => _MesArticleState();
}
class _MesArticleState extends State<MesArticles> {
#override
Widget build(BuildContext context) {
print(widget.idboutique.toString()); // it print null for fist time. After hot reload it become not null
return Scaffold(
body: Text(widget.idboutique.toString()), //<== it print null for fist time.
);
}
}
Try this code. I think Future builder is the reason it throws null.
class BoutiquePage extends StatefulWidget {
int idboutique;
BoutiquePage({this.idboutique});
#override
_BoutiquePageState createState() => _BoutiquePageState();
}
class _BoutiquePageState extends State<BoutiquePage> {
SharedPreferences sharedPreferences;
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
String idBou ;
String nomAbon ;
String prenomAbon ;
String telAbon ;
String addAbon;
String nomBou;
String ville;
String pays;
String lien_photo_bout;
bool _isLoading = false;
bool _isLoaded = false;
bool _isError = false;
String _errorText;
get article_afficher333 => article_afficher333;
#override
void initState() {
setState((){
getShaerInstance();
});
super.initState();
}
getShaerInstance() async {
sharedPreferences = await SharedPreferences.getInstance();
}
Future<Map<String, dynamic>> getAllStoreInfoData2(int idboutique) async {
final response = await http.get("http://xxxxxx.com/" + "boutique/home?id_bout="+idboutique.toString());
if (response.statusCode == 200) {
final jsonResponse = json.decode(response.body);
BoutiqueData myData = new BoutiqueData.fromJson(jsonResponse);
Map<String, dynamic> boutiqueinfodata = Map();
boutiqueinfodata["boutiqueType"] = myData.v_boutique.typeBoutique;
return boutiqueinfodata;
} else {
throw Exception("Failed to load Data");
}
}
//SharedPreferences
initDataFromServer(idboutique) async {
try {
var alldata = await getAllStoreInfoData2(idboutique);
var typeBoutique = alldata["boutiqueType"];
List<ListeInfoBoutique> boutiqueInfoData = alldata["boutiqueInfoData"];
for (var i = 0; i < boutiqueInfoData.length; i++) {
idBou = boutiqueInfoData[i].idBou;
nomAbon = boutiqueInfoData[i].nomAbon;
prenomAbon = boutiqueInfoData[i].prenomAbon;
telAbon = boutiqueInfoData[i].telAbon;
addAbon = boutiqueInfoData[i].addAbon;
}
setState(() {
_isLoaded = true;
_isLoading = false;
_isError = false;
});
} catch (e) {
print(e);
setState(() {
_isLoaded = true;
_isLoading = true;
_isError = true;
});
}
}
#override
Widget build(BuildContext context) {
if (_isLoaded == false && _isLoading == false) {
_isLoading = true;
initDataFromServer(widget.idboutique);
}
return DefaultTabController(
length: 5,
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text(AppLocalizations.of(context)
.translate('_MY_STORE'), style: TextStyle(color: Colors.white, fontFamily: "Questrial"),),
iconTheme: new IconThemeData(color: Color(0xFFFFFFFF)),
actions: <Widget>[
//
],
bottom: TabBar(
isScrollable: true,
indicatorColor: Colors.white,
indicatorWeight: 5.0,
//onTap: (){},
tabs: <Widget>[
Tab(
child: Container(
child: Text(AppLocalizations.of(context)
.translate('_STORE_INFO'), style: TextStyle(color: Colors.white, fontSize: 18.0, fontFamily: 'Questrial'),),
),
),
Tab(
child: Container(
child: Text(AppLocalizations.of(context)
.translate('_MY_ARTICLES'), style: TextStyle(color: Colors.white, fontSize: 18.0, fontFamily: 'Questrial'),),
),
),
],
),
),
body: TabBarView(
children: <Widget>[
_isLoaded == false ? Center(
child: CircularProgressIndicator(),
): (_isError == false ? Text("Your data Loaded") : Text("Error")),
_isLoaded == false ? Center(
child: CircularProgressIndicator(),
): (_isError == false ? MesArticles(idboutique: idboutique) : Text("Error")),
],
),
),
);
}
}
class MesArticles extends StatefulWidget {
final String idboutique;
const MesArticles({Key key, this.idboutique}) : super(key: key);
#override
_MesArticleState createState() => _MesArticleState(idboutique: idboutique);
}
class _MesArticleState extends State<MesArticles> {
final String idboutique;
_MesArticleState({this.idboutique});
#override
Widget build(BuildContext context) {
print(widget.idboutique.toString()); // it print null for fist time. After hot reload it become not null
return Scaffold(
body: Text(widget.idboutique.toString()),
);
}
}

Is it possible to send a query type url to Future in Flutter?

I need to shape myUrl inside Future related to username which I got from myfirstpage, I can get the name and use it in my homepage title but I couldn't figured out how can I use it in myUrl(instead of "$_name"),
Probably I made a mistake with point to data with "pushNamed(MyHomePage.routeName);" actually I don't need that value in MyHomePage, I just need it for shape myUrl line, also I tried to make "_name" value as a global value etc just not couldn't succeed..
import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
import 'dart:convert';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
new GlobalKey<RefreshIndicatorState>();
Future<bool> saveNamedPreference(String name) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString("name", name);
return prefs.commit();
}
Future<String> getNamePreferences() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String name = prefs.getString("name");
return name;
}
Payload payloadFromJson(String str) {
return Payload.fromJson(json.decode(str));
}
String payloadToJson(Payload data) {
return json.encode(data.toJson());
}
Future<Payload> getData() async{
String myUrl = 'http://lunedor.pythonanywhere.com/query?username=$_name';
http.Response response = await http.get(myUrl);
print(myUrl);
return response == null ? getData() : payloadFromJson(response.body);
}
class Payload {
String moviecast;
String moviedirectors;
String moviegenre;
String movieposterurl;
String movierating;
String movieruntime;
String moviesummary;
String movietitle;
String moviewriters;
String movieyear;
Payload({
this.moviecast,
this.moviedirectors,
this.moviegenre,
this.movieposterurl,
this.movierating,
this.movieruntime,
this.moviesummary,
this.movietitle,
this.moviewriters,
this.movieyear,
});
factory Payload.fromJson(Map<String, dynamic> json) => Payload(
moviecast: json["Actors"],
moviedirectors: json["Director"],
moviegenre: json["Genre"],
movieposterurl: json["Poster"],
movierating: json["imdbRating"],
movieruntime: json["Runtime"],
moviesummary: json["Plot"],
movietitle: json["Title"],
moviewriters: json["Writer"],
movieyear: json["Year"],
);
Map<String, dynamic> toJson() => {
"moviecast": moviecast,
"moviedirectors": moviedirectors,
"moviegenre": moviegenre,
"movieposterurl": movieposterurl.replaceAll('300.jpg', '900.jpg'),
"movierating": movierating,
"movieruntime": movieruntime,
"moviesummary": moviesummary,
"movietitle": movietitle,
"moviewriters": moviewriters,
"movieyear": movieyear,
};
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Random Movie',
theme: new ThemeData(
primarySwatch: Colors.grey,
),
home: new MyFirstPage(),
routes: <String, WidgetBuilder>{
MyHomePage.routeName: (context) => new MyHomePage(),
},
);
}
}
class MyFirstPage extends StatefulWidget {
#override
_MyFirstPageState createState() => new _MyFirstPageState();
}
class _MyFirstPageState extends State<MyFirstPage>{
var _controller = new TextEditingController();
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
backgroundColor: Colors.blueGrey,
centerTitle: true,
title: new Text("Please enter your Trakt username",
style: new TextStyle(
fontSize: 18.0,
color: Colors.white,
),
),
),
body: new ListView(
children: <Widget>[
new ListTile(
title: new TextField(
controller: _controller,
),
),
new ListTile(
title: new RaisedButton(
child: new Text("Submit"),
onPressed:(){setState(() {
saveName();
});
}),
)
],
),
);
}
void saveName() {
String name = _controller.text;
saveNamedPreference(name).then((bool committed) {
Navigator.of(context).pushNamed(MyHomePage.routeName);
});
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
static String routeName = "/myHomePage";
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
Payload payload;
class _MyHomePageState extends State<MyHomePage> {
Modal modal = Modal();
bool isLoading = true;
String _name = "";
#override
void initState() {
// TODO: implement initState
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {loadData();
WidgetsBinding.instance.addPostFrameCallback((_) => _refreshIndicatorKey.currentState.show());
getNamePreferences().then(updateName);
});
}
void loadData() async {
payload = await getData();
isLoading = false;
setState(() {});
print('${payload.movieposterurl.replaceAll('300.jpg', '900.jpg')}');
}
void updateName(String name) {
setState(() {
this._name = name;
ValueKey(_name);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar:
AppBar(
backgroundColor: Colors.blueGrey,
title:
isLoading ? Center(child: CircularProgressIndicator()):Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Center(
child: Text('${payload.movietitle}', maxLines: 2, textAlign: TextAlign.center,
style: new TextStyle(
fontSize: 18.0,
color: Colors.white,
),
),
),
Text('${payload.movieyear}' + " - " + _name + " - " + '${payload.movierating}',
style: new TextStyle(
fontSize: 14.0,
color: Colors.black,
fontStyle: FontStyle.italic,),
),
]
),
),
),
body:
isLoading ? Center(child: CircularProgressIndicator()):
RefreshIndicator(
key: _refreshIndicatorKey,
onRefresh: () async{payload = await getData();
isLoading = false;
setState(() {});
},
child: Center(
child:ListView(
shrinkWrap: true,
children: [
FittedBox(
alignment: Alignment.center,
child:
Image.network('${payload.movieposterurl.replaceAll('300.jpg', '900.jpg')}'),
),
]
)
)
),
bottomNavigationBar: isLoading ? Center(child: CircularProgressIndicator()):
BottomAppBar(
child: Container(
color: Colors.grey,
child: SizedBox(
width: double.infinity,
child:
FlatButton(
color: Colors.grey,
textColor: Colors.black,
onPressed: () {
modal.mainBottomSheet(context);
},
child: Text("Details",
style: TextStyle(fontSize: 16.0),),
),
),
),
),
);
}
}
class Modal {
mainBottomSheet(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
_createTile(
context, "Genre: " + payload.moviegenre + "\n" + "Runtime: " + payload.movieruntime, Icons.local_movies,
_action),
_createTile(
context, "Director: " + payload.moviedirectors,
Icons.movie_creation,
_action),
_createTile(
context, "Writer: " + payload.moviewriters,
Icons.movie,
_action),
_createTile(
context, "Cast: " + payload.moviecast, Icons.chrome_reader_mode,
_action),
_createTile(
context, "Summary: " + payload.moviesummary, Icons.recent_actors, _action),
],
),
);
}
);
}
ListTile _createTile(BuildContext context, String name, IconData icon,
Function action) {
return ListTile(
leading: Icon(icon),
title: Text(name),
onTap: () {
Navigator.pop(context);
action();
},
);
}
_action() {
print('action');
}
}
Not completely sure I got your question, but it should be enough to modify your getData() method to accept a String in parameters, at the moment getData() is a top-level function that doesn't know the _name value because is a private instance variable of _MyHomePageState
Future<Payload> getData(String name) async{
String myUrl = 'http://lunedor.pythonanywhere.com/query?username=$name';
http.Response response = await http.get(myUrl);
print(myUrl);
return response == null ? getData() : payloadFromJson(response.body);
}
And then in your loadData() method pass the correct value
void loadData() async {
payload = await getData(_name);
isLoading = false;
setState(() {});
print('${payload.movieposterurl.replaceAll('300.jpg', '900.jpg')}');
}
One last thing, you should add the "reload" logic when you change the name
void updateName(String name) {
setState(() {
isLoading = true;
this._name = name;
ValueKey(_name);
loadData();
});
}
Personally I think that the Payload variable should stay inside your _MyHomePageState class

Dropdown in flutter from LIST

Displaying the data from my API based on the Dropdown selected value. I want to display on the same page. The data from the server(response) is displaying on the console. But still, this data is not displaying.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
//import 'package:json_parsing_example/model2.dart';
//import 'package:json_parsing_example/models.dart'
List<YouModel> youModelFromJson(String str) => List<YouModel>.from(json.decode(str).map((x) => YouModel.fromJson(x)));
String youModelToJson(List<YouModel> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class YouModel {
String columnName;
YouModel({
this.columnName,
});
factory YouModel.fromJson(Map<String, dynamic> json) => YouModel(
columnName: json["column_name"],
);
Map<String, dynamic> toJson() => {
"column_name": columnName,
};
}
UserModel userModelFromJson(String str) => UserModel.fromJson(json.decode(str));
String userModelToJson(UserModel data) => json.encode(data.toJson());
class UserModel {
String username;
String name;
UserModel({
this.username,
this.name,
});
factory UserModel.fromJson(Map<String, dynamic> json) => UserModel(
username: json["username"],
name: json["Name"],
);
Map<String, dynamic> toJson() => {
"username": username,
"Name": name,
};
}
class Addoffers2 extends StatefulWidget {
#override
State<StatefulWidget> createState() => _Addoffers2State();
}
class _Addoffers2State extends State<Addoffers2> {
List<String> _companies = [];
bool _isLoading = false;
String _selectedCompany;
#override
void initState() {
super.initState();
_selectedCompany=null;
_getcompanylist();
}
Future<String> loadFromAssets() async {
return await rootBundle.loadString('json/parse.json');
}
_getcompanylist() async {
setState(() {
_isLoading = true;
});
print("getting..");
final responseStr =
await http.get('http://10.0.2.2/Flutter/GetCompanieslist.php');
//String responseStr = await loadFromAssets();
final listData = youModelFromJson(responseStr.body);
for(int i=0;i<listData.length;i++)
{
print('this is the list :'+listData[i].columnName);
// _companies.add(listData[i].columnName);
}
// above method is the standard method to get creating a model class and then get the list of strings
// I have just shown you but example is according to you code .
// this above loadFromAssets is that you hit the api and you get the json string response
// i have created a dummy json file where i can the String.
// Else everything is the same as below you just have to pass the response.body to the json.decode method.
var jsonData = json.decode(responseStr.body);
for (var u in jsonData) {
_companies.add(u.toString().substring(14, u.toString().length - 1));
}
for (int i = 0; i < _companies.length; i++) {
print(_companies[i].toString());
}
setState(() {
_isLoading = false;
});
}
#override
Widget build(BuildContext context) {
//double width = MediaQuery.of(context).size.width;
//double height = MediaQuery.of(context).size.height;
return MaterialApp(
//color: Colors.red,
home: Scaffold(
backgroundColor: Colors.red,
appBar: AppBar(
backgroundColor: Theme.of(context).backgroundColor,
title: Text("Add.."),
),
body: Container(
color: Colors.blue,
// just put your height i have modified it replace it by height / 8
child: _isLoading
? CircularProgressIndicator()
: Center(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
//MainAxisAlignment: MainAxisAlignment.spaceBetween,
Text('Choose..'),
DropdownButtonHideUnderline(
child: DropdownButton(
// hint: Text('Choose Company'), // Not necessary for Option 1
value: _selectedCompany,
onChanged: (newValue) {
setState(() {
_selectedCompany = newValue;
// here i have taken the boolen variable to show and hide the list if you have not seleted the value from the dropdown the it will show the text and if selected the it will show you the list.
});
print(_selectedCompany);
},
items: _companies.map((company) {
return DropdownMenuItem(
child: new Text(company.toString()),
value: company,
);
}).toList(),
),
),
],
),
),
),
// this is to to check for the initial if string is null then show the text widget.
// else if the value is selected then it will show the listview
_selectedCompany == null
? Text('Select the dropdown value for list to appear.')// sample text you can modify
: Padding(
padding: const EdgeInsets.all(0.0),
child: Container(
height: 100,
color: Theme.of(context).backgroundColor,
child: new FutureBuilder(
future: _getUsers(
_selectedCompany), // a Future<String> or null
builder: (BuildContext context,
AsyncSnapshot snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return Container(
child: Center(
child: new CircularProgressIndicator(
backgroundColor: Colors.white,
),
));
}
if (snapshot.hasError) {
return Center(
child: new Text(
'Error ${snapshot.error}'),
);
} else {
return Center(
child: Padding(
padding: const EdgeInsets.fromLTRB(
5.0, 8.0, 5.0, 8.0),
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder:
(BuildContext context,
int index) {
List<UserModel> user =
snapshot.data;
var username =
user[index].username;
var stuname =
user[index].name;
print(
'This is the user name :$username');
print(
'This is the name : $stuname');
//var title=snapshot.data[index]["Title"];
// new Text(parsedDate.toString());
return StudentList2(
regdNo: username,
name: stuname);
}),
),
);
}
}),
),
),
],
)),
)),
);
}
}
Future<String> loadFromAssets2() async {
return await rootBundle.loadString('json/parse2.json');
}
// the above method is just for the sample purpose where you get you json String after hitting the api call for _getUsers method
Future<List<UserModel>> _getUsers(String selectedcompany) async {
// here you call you api and you get the response
var url = 'https://10.0.2.2/Flutter/getstudentdata.php;
var data = { 'company': selectedcompany};
// Starting Web Call with data.
var response = await http.post(url, body: json.encode(data));
print(response.body);
//String responseStr = await loadFromAssets2();
final userModel = userModelFromJson(response.body);
// I have just made the model class for where fromt he below you get the complete object and then added to the list and returned.
List<UserModel> users = [];
users.add(userModel);
print('This is the name : ${users[0].name}'); // Even this also not getting printed
return users;
}
class StudentList2 extends StatefulWidget {
final regdNo;
final name;
const StudentList2({
Key key,
this.regdNo,
this.name,
}) : super(key: key);
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<StudentList2> {
bool visible = false;
#override
Widget build(BuildContext context) {
print(widget.regdNo.toString());
return Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: new Card(
color: Theme.of(context).primaryColor,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 2.0),
child: Container(
child: new Text(
widget.regdNo.toUpperCase(),
style: TextStyle(
color: Colors.yellowAccent,
fontWeight: FontWeight.bold,
fontSize: 15.0,
),
),
),
),
ListTile(
title: new Text(
widget.regdNo,
style: TextStyle(
color: Colors.black,
fontSize: 14.0,
),
),
subtitle: new Text(
(widget.name),
style: TextStyle(
color: Colors.black,
fontSize: 15.0,
),
),
),
//
],
)),
);
}
}
I am able to retrieve the data from the server and print it on the console. Still, the data is not displaying. I do not know where I did the mistake.
So I have completely updated the answer and there are many things that you don't follow according to the global standard.
So I have listed some of the key things that you should follow :
Following is you company list json :
[
{
"column_name": "ABC"
},
{
"column_name": "XYZ"
}
]
Following is the get user json that you will get :
{"username":"1111","Name":"ABC" }
And Later the model class I have create accordingly to the json that you provided and then you can create your own based in the added json.
There are Two model classes that I have created :
First model class is for the company :
// To parse this JSON data, do
//
// final youModel = youModelFromJson(jsonString);
import 'dart:convert';
List<YouModel> youModelFromJson(String str) => List<YouModel>.from(json.decode(str).map((x) => YouModel.fromJson(x)));
String youModelToJson(List<YouModel> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class YouModel {
String columnName;
YouModel({
this.columnName,
});
factory YouModel.fromJson(Map<String, dynamic> json) => YouModel(
columnName: json["column_name"],
);
Map<String, dynamic> toJson() => {
"column_name": columnName,
};
}
second mode class is for the user :
// To parse this JSON data, do
//
// final userModel = userModelFromJson(jsonString);
import 'dart:convert';
UserModel userModelFromJson(String str) => UserModel.fromJson(json.decode(str));
String userModelToJson(UserModel data) => json.encode(data.toJson());
class UserModel {
String username;
String name;
UserModel({
this.username,
this.name,
});
factory UserModel.fromJson(Map<String, dynamic> json) => UserModel(
username: json["username"],
name: json["Name"],
);
Map<String, dynamic> toJson() => {
"username": username,
"Name": name,
};
}
Below is the main ui file just Check the comments that I have made so that it will be helpful for you .
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:json_parsing_example/model2.dart';
import 'package:json_parsing_example/models.dart';
void main() => runApp(Addoffers());
class Addoffers extends StatefulWidget {
#override
State<StatefulWidget> createState() => _AddoffersState();
}
class _AddoffersState extends State<Addoffers> {
List<String> _companies = [];
bool _isLoading = false;
String _selectedCompany;
#override
void initState() {
super.initState();
_selectedCompany=null;
_getcompanylist();
}
Future<String> loadFromAssets() async {
return await rootBundle.loadString('json/parse.json');
}
_getcompanylist() async {
setState(() {
_isLoading = true;
});
print("getting..");
/* final response =
await http.get('http://10.0.2.2/Flutter/GetCompanieslist.php'); */
String responseStr = await loadFromAssets();
final listData = youModelFromJson(responseStr);
for(int i=0;i<listData.length;i++)
{
print('this is the list :'+listData[i].columnName);
// _companies.add(listData[i].columnName);
}
// above method is the standard method to get creating a model class and then get the list of strings
// I have just shown you but example is according to you code .
// this above loadFromAssets is that you hit the api and you get the json string response
// i have created a dummy json file where i can the String.
// Else everything is the same as below you just have to pass the response.body to the json.decode method.
var jsonData = json.decode(responseStr);
for (var u in jsonData) {
_companies.add(u.toString().substring(14, u.toString().length - 1));
}
for (int i = 0; i < _companies.length; i++) {
print(_companies[i].toString());
}
setState(() {
_isLoading = false;
});
}
#override
Widget build(BuildContext context) {
//double width = MediaQuery.of(context).size.width;
//double height = MediaQuery.of(context).size.height;
return MaterialApp(
//color: Colors.red,
home: Scaffold(
backgroundColor: Colors.red,
appBar: AppBar(
backgroundColor: Theme.of(context).backgroundColor,
title: Text("Add.."),
),
body: Container(
color: Colors.blue,
// just put your height i have modified it replace it by height / 8
child: _isLoading
? CircularProgressIndicator()
: Center(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
//MainAxisAlignment: MainAxisAlignment.spaceBetween,
Text('Choose..'),
DropdownButtonHideUnderline(
child: DropdownButton(
// hint: Text('Choose Company'), // Not necessary for Option 1
value: _selectedCompany,
onChanged: (newValue) {
setState(() {
_selectedCompany = newValue;
// here i have taken the boolen variable to show and hide the list if you have not seleted the value from the dropdown the it will show the text and if selected the it will show you the list.
});
print(_selectedCompany);
},
items: _companies.map((company) {
return DropdownMenuItem(
child: new Text(company.toString()),
value: company,
);
}).toList(),
),
),
],
),
),
),
// this is to to check for the initial if string is null then show the text widget.
// else if the value is selected then it will show the listview
_selectedCompany == null
? Text('Select the dropdown value for list to appear.')// sample text you can modify
: Padding(
padding: const EdgeInsets.all(0.0),
child: Container(
height: 100,
color: Theme.of(context).backgroundColor,
child: new FutureBuilder(
future: _getUsers(
_selectedCompany), // a Future<String> or null
builder: (BuildContext context,
AsyncSnapshot snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return Container(
child: Center(
child: new CircularProgressIndicator(
backgroundColor: Colors.white,
),
));
}
if (snapshot.hasError) {
return Center(
child: new Text(
'Error ${snapshot.error}'),
);
} else {
return Center(
child: Padding(
padding: const EdgeInsets.fromLTRB(
5.0, 8.0, 5.0, 8.0),
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder:
(BuildContext context,
int index) {
List<UserModel> user =
snapshot.data;
var username =
user[index].username;
var stuname =
user[index].name;
print(
'This is the user name :$username');
print(
'This is the name : $stuname');
//var title=snapshot.data[index]["Title"];
// new Text(parsedDate.toString());
return StudentList2(
regdNo: username,
name: stuname);
}),
),
);
}
}),
),
),
],
)),
)),
);
}
}
Future<String> loadFromAssets2() async {
return await rootBundle.loadString('json/parse2.json');
}
// the above method is just for the sample purpose where you get you json String after hitting the api call for _getUsers method
Future<List<UserModel>> _getUsers(String selectedcompany) async {
/* var data = await http.post("http://10.0.2.2/Flutter/getstdata.php", body: {
"company": selectedcompany,
//print(data.body);
}); */
// here you call you api and you get the response
String responseStr = await loadFromAssets2();
final userModel = userModelFromJson(responseStr);
// I have just made the model class for where fromt he below you get the complete object and then added to the list and returned.
List<UserModel> users = [];
users.add(userModel);
print('This is the name : ${users[0].name}');
//final x=users.length.toString();
//debugPrint("records:" + users.length.toString());
//debugPrint("kkk:" + absentees.length.toString());
return users;
}
class StudentList2 extends StatefulWidget {
//MyHomePage(String branch);
final regdNo;
final name;
const StudentList2({
Key key,
this.regdNo,
this.name,
}) : super(key: key);
//final String branch;
//const StudentList({Key key, this.branch}) : super(key: key);
//MyHomePage(String branch);
// final String title;
// final String branch="";
// MyHomePage(String branch, {Key key, this.title}) : super(key: key);
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<StudentList2> {
bool visible = false;
//bool _btnEnabled = false;
//bool _validate = false;
// var _firstPress = true ;
//Color _iconColor = Colors.yellow;
//Color _iconColor2 = Colors.white;
//var poll;
//DateTime parsedDate;
#override
Widget build(BuildContext context) {
print(widget.regdNo.toString());
return Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: new Card(
color: Theme.of(context).primaryColor,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 2.0),
child: Container(
child: new Text(
widget.regdNo.toUpperCase(),
style: TextStyle(
color: Colors.yellowAccent,
fontWeight: FontWeight.bold,
fontSize: 15.0,
),
),
),
),
ListTile(
title: new Text(
widget.regdNo,
style: TextStyle(
color: Colors.black,
fontSize: 14.0,
),
),
subtitle: new Text(
(widget.name),
style: TextStyle(
color: Colors.black,
fontSize: 15.0,
),
),
),
//
],
)),
);
}
}
// This is not the good approach to create a model class just check the sample model class that i have created.
class User {
//final int index;
final String username;
final String name;
//final Float cgpa;
User(
this.username,
this.name,
);
}
And below is the sample Gif file for you :
As stated by #pskink the method _getcompanylist() is async. An async function runs asynchronously, which means that the rest of the program doesn't wait for it to complete. You can use a future builder to deal whit that or you can simply wait for it by using the await function. I believe that for your code snippet future builder is the better choice.