Map<dynamic,dynamic> is null after loading currencies from API - flutter

Any idea why my currencies map is null in the CurrencyConverterState class? I am loading currencies from an API to my currencies map in class API (see code for class API) and also trying to set state after the loading is done. After loading the currencies from the API to my currencies map I can also access the rates from the map so that means that my map is working fine and is not null. I did that test by printing a currency rate and it was fine. But that works just in the API class. The problem is that as soon as I test my currencies map in class CurrencyConverterState it says that the map is null and I am stuck in circular progress indicator (see code for class CurrencyConverterState). I dont really know why it says that the map is null. Any help appreciated.
API class code:
class API
{
var fromTextController = new TextEditingController();
Map<dynamic, dynamic> currencies;
String fromCurrency;
String toCurrency;
String result;
API(String from, String to){
fromCurrency = from;
toCurrency = to;
}
Future<dynamic> loadCurrencies() async {
String uri = "http://api.openrates.io/latest";
var response = await http
.get(Uri.encodeFull(uri), headers: {"Accept": "application/json"});
var responseBody = json.decode(response.body);
Map curMap = responseBody['rates'];
currencies = curMap;
setState(() {});
print (currencies["SEK"]);
}
Future<dynamic> doConversion() async {
String uri =
"http://api.openrates.io/latest?base=$fromCurrency&symbols=$toCurrency";
var response = await http
.get(Uri.encodeFull(uri), headers: {"Accept": "application/json"});
var responseBody = json.decode(response.body);
setState(() {
result = (double.parse(fromTextController.text) *
(responseBody["rates"][toCurrency]))
.toString();
});
setState(() {});
return "Success";
}
void setState(Null Function() param0) {}
}
CurrencyConverterState class code:
class CurrencyConverterState extends State<CurrencyConverter> {
final API api = new API("USD", "SEK");
CurrencyConverterState();
int i = 1;
#override
void initState() {
super.initState();
api.loadCurrencies();
api.fromTextController.addListener(doConversion);
setState(() {
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
backgroundColor: Theme.of(context).primaryColor,
body: api.currencies?.keys == null
? Center(child: CircularProgressIndicator())
: Stack(children: [
Positioned(
top: 30,
child: Container(
alignment: Alignment.center,
height: MediaQuery.of(context).size.height / 2,
width: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
elevation: 10,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
'Converter',
style: TextStyle(
color: Colors.black, fontSize: 22.0),
),
ListTile(
title: TextField(
controller: api.fromTextController,
decoration: InputDecoration(
hintText: 'Enter a number'),
style: TextStyle(
fontSize: 20.0, color: Colors.black),
keyboardType: TextInputType.numberWithOptions(
decimal: true),
),
trailing:
buildDropDownButton(api.fromCurrency),
),
ListTile(
title: Chip(
label: api.result != null
? Container(
width: 1000,
height: 40,
child: Text(
api.result,
style: Theme.of(context)
.textTheme
.headline4,
),
)
: Container(
width: 1000,
height: 40,
child: Text(" "))),
trailing:
buildDropDownButton(api.toCurrency),
),
],
)),
),
),
),
]));
}
Widget buildDropDownButton(String currencyCategory) {
return DropdownButton(
value: currencyCategory,
dropdownColor: Colors.white,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
items: api.currencies.keys.map((dynamic value) => DropdownMenuItem(
value: value,
child: Row(children: <Widget>[
Text(value),
])))
.toList(),
onChanged: (dynamic value) {
if (currencyCategory == api.fromCurrency) {
api.fromCurrency = value;
} else {
api.toCurrency = value;
}
setState(() {});
});
}
doConversion() {
api.doConversion();
setState(() {});
}
}

Actually, you are retrieving currencies before they get retrieved and you are never updating the UIs when they are retrieved.
This is a possible solution:
//In API class
Future<Map<String,dynamic>> loadCurrencies() async {
String uri = "http://api.openrates.io/latest";
var response = await http
.get(Uri.encodeFull(uri), headers: {"Accept": "application/json"});
var responseBody = json.decode(response.body);
Map<String,dynamic> curMap = responseBody['rates'];
print (currencies["SEK"]);
return curMap;
}
Then in your main class use a futureBuilder:
return Scaffold(
resizeToAvoidBottomPadding: false,
backgroundColor: Theme.of(context).primaryColor,
body: FutureBuilder(
future: api.loadCurrencies(),
builder: (context, currencies) =>{
return currencies==null?
? Center(child: CircularProgressIndicator())
: Stack(/*rest of your code*/);
})
);

Related

Error : Failed to detect image file format using the file header. File header was [0x3c 0x68 0x74 0x6d 0x6c 0x3e 0x0a 0x20 0x20 0x20]

I'm trying to display an image from Firestore in to my UI. But it returns the error above, and the file format also changes when I run it on Edge (not on physical device or Emulator). I can't figure out how. Here's my code.
class ViewPola extends StatefulWidget {
const ViewPola({Key? key}) : super(key: key);
static String id = 'view_pola';
#override
State<ViewPola> createState() => _ViewPolaState();
}
class _ViewPolaState extends State<ViewPola> {
Function getSnaps = () async {
final polaMap = {
'Kode Pola': '',
'Bagian Pola': '',
'image_url': '',
};
FirebaseFirestore.instance
.collection('PolaWillyJKT')
.limit(1)
.get()
.then((snapshot) {
if (snapshot.size == 0) {
FirebaseFirestore.instance.collection('PolaWillyJKT').add(polaMap);
FirebaseFirestore.instance.collection('PolaWillyJKT');
print('add');
} else {
print('disini nge get');
var a = FirebaseFirestore.instance.collection('PolaWillyJKT').get();
Map<String, dynamic> data = a as Map<String, dynamic>;
print(data);
}
});
};
var _selectedItem;
var _showList = false;
#override
void initState() {
getSnaps();
super.initState();
}
final Stream<QuerySnapshot> _polaWilly =
FirebaseFirestore.instance.collection('PolaWillyJKT').snapshots();
#override
Widget build(BuildContext context) {
final screenHeight = ScreenInfo.screenHeight(context);
final screenWidth = ScreenInfo.screenWidth(context);
return StreamBuilder<QuerySnapshot>(
stream: _polaWilly,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return SafeArea(
child: Scaffold(
body: Padding(
padding: EdgeInsets.all(25),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Text(
'Pilih Bagian Pola',
style: TextStyle(fontSize: 25),
),
const SizedBox(
height: 20,
),
DropdownButton(
isExpanded: true,
value: _selectedItem,
items: snapshot.data?.docs
.map(
(value) => DropdownMenuItem(
value: value.get("Bagian Pola"),
child: Text('${value.get("Bagian Pola")}'),
),
)
.toList(),
onChanged: (newValue) {
setState(() {
_selectedItem = newValue.toString();
_showList = true;
});
}),
Padding(
padding: const EdgeInsets.all(25),
child: Visibility(
visible: _showList,
child: Container(
height: screenHeight * 0.4,
child: ListView(
children: snapshot.data!.docs
.where(
(e) => e.get("Bagian Pola") == _selectedItem)
.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return Center(
child: Column(
children: [
Text(
'Bagian Pola: ${data["Bagian Pola"]}',
style: TextStyle(fontSize: 15),
),
const SizedBox(
height: 15,
),
Text(
'Kode Pola : ${data["Kode Pola"]}',
style: TextStyle(fontSize: 15),
),
const SizedBox(
height: 15,
),
Image(
image:
NetworkImage(document.get("Foto Pola")),
height: 200,
width: 200,
), // this is the Image widget where I tried to put the image from firestore
Text(document.get('Foto Pola').toString()),
],
),
);
}).toList(),
),
),
),
),
],
),
),
),
);
},
);
}
}
and here's the class that uploads the image to Firestore
class Input_Pola extends StatefulWidget {
const Input_Pola({Key? key}) : super(key: key);
static String id = 'input_pola';
#override
State<Input_Pola> createState() => _Input_PolaState();
}
class _Input_PolaState extends State<Input_Pola> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
void _checkDuplicate() {
if (options.contains(_textfieldValue.text)) {
// Display bottom sheet that says item already exists
_scaffoldKey.currentState?.showBottomSheet((context) => Container(
height: 300,
child: Column(
children: [
const Text('Item already exists'),
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Dismiss'))
],
),
));
} else {
// Add item to options list
setState(() {
options.add(_textfieldValue.text);
});
}
}
XFile? image;
final ImagePicker picker = ImagePicker();
String _image_url = '';
void _addToFirebase(String dropdownValue, String _kodePolaController) {
var imageFile = File(image!.path);
String fileName = pth.basename(imageFile.path);
FirebaseStorage storage = FirebaseStorage.instance;
Reference ref = storage.ref().child("WillyJKT/polaWillyJKT");
UploadTask uploadTask = ref.putFile(imageFile);
uploadTask.whenComplete(() async {
var url = await ref.getDownloadURL();
_image_url = url.toString();
});
FirebaseFirestore.instance
.collection('PolaWillyJKT')
.doc(_selectedOption)
.set({
'Bagian Pola': _selectedOption,
'Kode Pola': _kodePolaController,
'Foto Pola': _image_url
});
}
String _dropdownValue = 'kg';
String _property1 = '';
String _property2 = '';
String _property3 = '';
bool _isOptionSelected = false;
final TextEditingController _kodePolaController = TextEditingController();
var _selectedOption;
final TextEditingController _textfieldValue = TextEditingController();
final List<String> options = [];
#override
void initState() {
super.initState();
_selectedOption = options.isNotEmpty ? options[0] : null;
}
//we can upload image from camera or from gallery based on parameter
Future getImage(ImageSource media) async {
var img = await picker.pickImage(source: media);
setState(() {
image = img;
});
}
void myAlert() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
title: Text('Please choose media to select'),
content: Container(
height: MediaQuery.of(context).size.height / 6,
child: Column(
children: [
ElevatedButton(
//if user click this button, user can upload image from gallery
onPressed: () {
Navigator.pop(context);
getImage(ImageSource.gallery);
},
child: Row(
children: [
Icon(Icons.image),
Text('From Gallery'),
],
),
),
ElevatedButton(
//if user click this button. user can upload image from camera
onPressed: () {
Navigator.pop(context);
getImage(ImageSource.camera);
},
child: Row(
children: [
Icon(Icons.camera),
Text('From Camera'),
],
),
),
],
),
),
);
});
}
#override
Widget build(BuildContext context) {
final screenHeight = ScreenInfo.screenHeight(context);
final screenWidth = ScreenInfo.screenWidth(context);
return SafeArea(
child: Scaffold(
key: _scaffoldKey,
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
_addToFirebase(_dropdownValue, _kodePolaController.text);
},
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(25),
child: Container(
height: screenHeight,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextFormField(
decoration: const InputDecoration(
hintText: 'Input Pola',
border: UnderlineInputBorder(),
),
onChanged: (value) {
setState(() {
_textfieldValue.text = value;
});
},
),
DropdownButton<String>(
value: _selectedOption,
onChanged: (value) {
setState(() {
_selectedOption = value!;
_isOptionSelected = true;
_kodePolaController.clear();
});
},
hint: const Text('Input from Text Field Above'),
items: options.map((option) {
return DropdownMenuItem<String>(
value: option,
child: Text(option),
);
}).toList(),
),
TextButton(
onPressed: _checkDuplicate,
child: const Text("Add Option"),
),
Visibility(
visible: _isOptionSelected,
child: Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
TextField(
controller: _kodePolaController,
decoration: const InputDecoration(
labelText: "Kode Pola"),
onChanged: (value) {
setState(() {
_property1 = value;
});
},
),
const SizedBox(height: 20,),
ElevatedButton(
onPressed: () {
myAlert();
},
child: Text('Upload Photo'),
),
SizedBox(
height: 10,
),
//if image not null show the image
//if image null show text
image != null
? Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.file(
//to show image, you type like this.
File(image!.path),
fit: BoxFit.cover,
width: MediaQuery.of(context).size.width,
height: 300,
),
),
)
: const Text(
"No Image",
style: TextStyle(fontSize: 20),
),
],
),
),
)
],
),
),
),
),
),
);
}
}
It also displays the error on Edge, but when I build the apk and run it on my physical device, it just shows nothing on the screen except for the data that's got above it. Any idea on how I can fix this?
var a = FirebaseFirestore.instance.collection('PolaWillyJKT').get();
This returns a promise but not the actual data. In fact it could still be fetching the data when you attempt to convert it to a map.
You can await
var a = await FirebaseFirestore.instance.collection('PolaWillyJKT').get();
myDoc = a.docs.first();
Or use a callback that will run once the collection fetch completes:
FirebaseFirestore.instance.collection('PolaWillyJKT').get().then((response) => {
print(response);
});

How to provide filled places in Flutter

First I want to introduce the pages.
Form Page
This is where I fill a form. When I click save as draft it will save the form data to the SQLite database. For now, I haven't implemented SQLite yet. Anyway, But I have a list that buffers the form input. When you click on Save as draft, I create a FormData object and add that data to a list and provide that list with Provider.
Form Page Code
class FormPage extends StatefulWidget {
FormData? formData = FormData();
FormPage({Key? key, this.formData}) : super(key: key);
#override
State<FormPage> createState() => _HomePageState();
}
class _HomePageState extends State<FormPage> {
String? isEmpty(String val) {
String? text;
setState(() {
if (val.isEmpty) {
text = 'Boş bırakılamaz';
}
});
return text;
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xffffe0b2),
appBar: AppBar(
// backgroundColor: Colors.teal.shade400,
title: const Text('Hasta Etkileşim Kaydı'),
centerTitle: true,
backgroundColor: const Color(0xffffb74d),
elevation: 0,
),
body: SafeArea(
child: FutureBuilder(
future: readJsonData(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text(snapshot.error.toString());
} else if (snapshot.hasData) {
var items = snapshot.data as List<dynamic>;
var listStajTuru = items[0].stajTuruItems;
var listCinsiyet = items[0].cinsiyetItems;
var listEtkilesim = items[0].etkilesimTuruItems;
var listKapsam = items[0].kapsamItems;
var listOrtam = items[0].ortamItems;
var listDoktor = items[0].doktorItems;
return Form(
key: _formKey,
child: ListView(
shrinkWrap: true,
children: [
myDropDownContainer(_valueStajTuru, listStajTuru,
hintTextStajTuru, onChangedStajTuru),
myDropDownContainer(_valueDoktor, listDoktor,
hintTextDoktor, onChangedDoktor),
myDropDownContainer(_valueCinsiyet, listCinsiyet,
hintTextCinsiyet, onChangedCinsiyet),
myDropDownContainer(_valueEtkilesim, listEtkilesim,
hintTextEtkilesim, onChangedEtkilesim),
myDropDownContainer(_valueKapsam, listKapsam,
hintTextKapsam, onChangedKapsam),
myDropDownContainer(_valueOrtam, listOrtam,
hintTextOrtam, onChangedOrtam),
myTextFieldRow(20, "Kayıt No: ", 10,
_formData.setKayitNo, isEmpty),
myTextFieldRow(
20, "Hastanın Yaşı:", 3, _formData.setYas, isEmpty),
myTextFieldRow(
20, "Şikayet:", 10, _formData.setSikayet, isEmpty),
myTextFieldRow(50, "Ayırıcı Tanı:", 50,
_formData.setAyiriciTani, isEmpty),
myTextFieldRow(50, "Kesin Tanı:", 50,
_formData.setKesinTani, isEmpty),
myTextFieldRow(50, "Tedavi Yöntemi:", 100,
_formData.setTedaviYontemi, isEmpty),
const SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
submitButton(context, "Sava as Draft"),
submitButton(context, "GÖNDER"),
],
),
],
),
);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
})),
);
}
//Kullanıcı kaydet butonuna basarsa local olarak kaydedecek
Container submitButton(BuildContext context, String title) {
return Container(
width: 120,
height: 50,
margin: const EdgeInsets.all(12),
child: TextButton(
onPressed: () {
setState(() {
if (_formKey.currentState!.validate()) {
Provider.of<FormAdd>(context, listen: false)
.addNewFormToList(_formData);
alertDialog(context).then((_) =>_formKey.currentState!.reset());
}
});
},
child: Text(
title,
style: kTextStyle.copyWith(
fontSize: 14, color: Colors.white, fontWeight: FontWeight.bold),
),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
const Color(0xffffa726),
),
),
),
);
}
//DropDownWidget
Container myDropDownContainer(String initialVal, List<String> listItems,
String text, Function myFunc) {
return Container(
margin: const EdgeInsets.all(8),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
width: 120,
child: Text(
text,
style: kTextStyle,
),
),
const SizedBox(
width: 20,
),
Expanded(
child: Container(
height: 50,
decoration: BoxDecoration(
color: Colors.orangeAccent,
borderRadius: BorderRadius.circular(5)),
child: DropdownButtonFormField<String>(
// autovalidateMode: AutovalidateMode.always,
//menuMaxHeight: 300,
validator: (value) {
if (value!.isEmpty) {
return "485s4a8sd4as85";
}
},
decoration: const InputDecoration(border: InputBorder.none),
isExpanded: true,
//onTap: () => myFunc,
//borderRadius: BorderRadius.circular(5),
value: initialVal,
icon: const Icon(
Icons.arrow_downward,
color: Colors.black38,
),
iconSize: 24,
elevation: 16,
dropdownColor: Colors.deepOrange,
style: kTextStyle.copyWith(color: Colors.black),
onChanged: (val) => myFunc(val),
items: listItems.map<DropdownMenuItem<String>>((String? val) {
return DropdownMenuItem(
//TODO: Set default values
value: val == null ? val = initialVal : val = val,
child: Text(
val,
style: kTextStyle.copyWith(color: Colors.black),
),
);
}).toList(),
),
),
)
],
),
);
}
//TextFieldWidget
Row myTextFieldRow(double height, String text, int? maxLength,
Function function, Function regexFunction) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 80,
height: height,
child: Text(
text,
style: kTextStyle.copyWith(color: Colors.black54),
),
),
const SizedBox(
width: 10,
),
Expanded(
child: TextFormField(
validator: (value) => regexFunction(value),
// focusNode: FocusNode(),
onChanged: (input) {
function(input);
},
autofocus: false,
textAlignVertical: TextAlignVertical.bottom,
style: kTextStyle.copyWith(fontSize: 16),
maxLength: maxLength,
maxLines: null, //TODO:Arrange maxlines for the inputs
decoration: InputDecoration(
isDense: true,
contentPadding: EdgeInsets.fromLTRB(0, 0, 0, height),
border: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.green),
borderRadius: BorderRadius.all(Radius.circular(3))),
// labelStyle:kTextStyle.copyWith(fontSize: 16, color: Colors.white54),
),
),
),
],
);
}
Future<List<FormContent>> readJsonData() async {
final jsonData =
await rootBundle.rootBundle.loadString('assets/json/formdata.json');
return [
for (final e in json.decode(jsonData)) FormContent.fromJson(e),
];
}
final _formKey = GlobalKey<FormState>();
final FormData _formData = FormData();
String _valueEtkilesim = "Gözlem";
String _valueKapsam = "Öykü";
String _valueOrtam = "Poliklinik";
String _valueDoktor = "Diğer";
String _valueStajTuru = "Ortopedi";
String _valueCinsiyet = "Erkek"; // initial value
final String hintTextCinsiyet = "Cinsiyet:";
final String hintTextStajTuru = "Staj Türü:";
final String hintTextEtkilesim = "Etkileşim Türü:";
final String hintTextKapsam = "Kapsam:";
final String hintTextOrtam = "Gerçekleştiği Ortam:";
final String hintTextDoktor = "Klinik Eğitici:";
void onChangedCinsiyet(String? newVal) {
setState(() {
_valueCinsiyet = newVal!;
_formData.setCinsiyet(_valueCinsiyet);
});
}
void onChangedStajTuru(String newVal) {
setState(() {
_valueStajTuru = newVal;
_formData.setStajTuru(newVal);
});
}
void onChangedEtkilesim(String newVal) {
setState(() {
_valueEtkilesim = newVal;
_formData.setEtkilesimTuru(newVal);
});
}
void onChangedKapsam(String newVal) {
setState(() {
_valueKapsam = newVal;
_formData.setKapsam(newVal);
});
}
void onChangedOrtam(String newVal) {
setState(() {
_valueOrtam = newVal;
_formData.setOrtam(newVal);
});
}
void onChangedDoktor(String newVal) {
setState(() {
_valueDoktor = newVal;
_formData.setDoktor(newVal);
});
}
}
Assume, we saved the form as a draft. Now, It is in the DraftsPage.
Drafts Page
Everything is alright up to now. I have a list of the saved in draft forms. When I click on any list item I could get the form information (3rd picture).
Here is the question.
When I click on the Edit button. I want to renavigate to the Form Page.However this time I want to fill the places with the relevant data. For instance, this time Kayıt No: TextField shouldn't be empty it must be filled with 555, because it was saved to draft. And unfilled places must be blank. I know I need to provide an object of the form(formData) but, I couldn't manage it. When I click on the Edit button. I should provide that object and use it in the Form Page to fill those forms. But, how?
Draft Code
class Drafts extends StatelessWidget {
#override
Widget build(BuildContext context) {
void pushToFormPage(FormData formData) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FormView(
formData: formData,
)));
}
List<FormData> _forms = Provider.of<FormAdd>(context).getForms();
return Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(
title: const Text("Taslaklar"),
centerTitle: true,
),
body: ListView.separated(
separatorBuilder: (BuildContext context, int index) => const Divider(
height: 5,
color: Colors.blueAccent,
),
itemCount: _forms.length,
itemBuilder: (BuildContext context, int index) {
return studentListViewInstanceContainer(
const Color.fromARGB(200, 200, 130, 240),
pushToFormPage,
_forms[index], context);
},
),
);
}
}
GestureDetector studentListViewInstanceContainer(
Color color, Function function, FormData formData,BuildContext context) {
return GestureDetector(
onTap: () => function(formData),
child: Container(
height: 100,
color: color,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Kayıt No: ${formData.getKayitNo()}',
style: kTextStyle,
),
Text(
'Tarih: ${formData.getKayitNo()}',
style: kTextStyle.copyWith(fontSize: 15),
) //TODO: implement DateT
],
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton(onPressed: (){
// taslağa kaydedilmiş bilgiler tekrar yüklenecek.
FormData data= Provider.of<FormData>(context,listen: false);
Navigator.push(context, MaterialPageRoute(builder: (context)=>FormPage(formData: data,)));
},
child:const Text('Edit'),
),
const SizedBox(width: 5,),
ElevatedButton(onPressed: (){
},
child: const Text('Delete'),
),
],
),
],
),
),
);
}
This is my FormData model class.
class FormData with ChangeNotifier{
String? _kayitNo;
String? _stajTuru;
String? _doktor; //TODO: Convert string to AttendingPhysician type object
// late AttendingPhysician klinikEgitici;
String? _yas; // TODO: Convert to string later
String? _cinsiyet;
String? _sikayet;
String? _ayiriciTani;
String? _kesinTani;
String? _tedaviYontemi;
String? _etkilesimTuru;
String? _kapsam;
String? _gerceklestigiOrtam;
//DateTime tarih;
String getKayitNo()=>_kayitNo!;
String getStajTuru()=>_stajTuru!;
String getDoktor()=>_doktor!;
String getYas()=>_yas!;
String getCinsiyet()=>_cinsiyet!;
String getSikayet()=>_sikayet!;
String getAyiriciTani()=>_ayiriciTani!;
String getKesinTani()=>_kesinTani!;
String getTedaviYontemi()=>_tedaviYontemi!;
String getEtkilesimTuru()=>_etkilesimTuru!;
String getKapsam()=>_kapsam!;
String getOrtam()=>_gerceklestigiOrtam!;
void setStajTuru(String stajTuru) {
_stajTuru = stajTuru;
notifyListeners();
}
void setCinsiyet(String cinsiyet) {
_cinsiyet = cinsiyet;
notifyListeners();
}
void setEtkilesimTuru(String etkilesim) {
_etkilesimTuru = etkilesim;
notifyListeners();
}
void setKapsam(String kapsam) {
_kapsam = kapsam;
notifyListeners();
}
void setOrtam(String ortam) {
_gerceklestigiOrtam = ortam;
notifyListeners();
}
void setKayitNo(String kayitNo) {
_kayitNo = kayitNo;
notifyListeners();
}
void setYas(String yas) {
_yas = yas;
notifyListeners();
}
void setSikayet(String sikayet) {
_sikayet = sikayet;
notifyListeners();
}
void setAyiriciTani(String ayiriciTani) {
_ayiriciTani = ayiriciTani;
notifyListeners();
}
void setKesinTani(String kesinTani) {
_kesinTani = kesinTani;
notifyListeners();
}
void setTedaviYontemi(String tedaviYontemi) {
_tedaviYontemi = tedaviYontemi;
notifyListeners();
}
void setDoktor(String doktor){
_doktor=doktor;
notifyListeners();
}
}
To make it easier to understand the question. This process is the same as saving mail as a draft. When you want to edit the mail, the unfinished mail will show up not an empty mail.

How to get parameters from URL in with Flutter

I want to show a list from LoanSimulation pages based on periodtime, interestpermonth and loanamountrequest
This is my Simulators function
static Future<LoanModel> simulators({String periodtime, String interestpermonth, String loanamountrequest, String idUser, String url}) async {
var uri = Uri(
scheme: 'http',
host: '192.168.0.23',
path: 'edufund-api/Api/loansimulation.php',
queryParameters: {
'periodtime': [periodtime], //from here get value
'interestpermonth' : [interestpermonth],
'loanamountrequest' : [loanamountrequest]
},
);
print(uri);
final response = await http.get(uri,headers:{"Content-Type":
"application/json"},
);
var res = LoanModel.fromJson(jsonDecode(response.body)[0]);
print(response.body);
return res;
}
This is my fetchdata from Simulator.dart
Future<LoanModel> _fetchData() async {
setState(() {
loading = true;
});
var uri = Uri(
scheme: 'http',
host: '192.168.0.23',
path: 'edufund-api/Api/loansimulation.php',
queryParameters: {
'periodtime': ["48"], //this is hard code i want to change the value same as simulators but it make error
'interestpermonth' : ["1"],
'loanamountrequest' : ["120000000"]
},
);
print(uri);
final response = await http.get(uri,headers:{"Content-Type":
"application/json"});
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
setState(() {
for (Map i in data) {
_loanmodel.add(LoanModel.fromJson(i));
}
loading = false;
});
}
}
So here is the result with hard code
And this is my Loan Model
LoanModel(
{this.no,
this.interest,
this.balance,
this.principal,
this.installment,
this.status,
this.message});
LoanModel.fromJson(Map<String, dynamic> json) {
interest = json['interest'];
balance = json['balance'];
principal = json['principal'];
installment = json['Installment'];
status = json['Status'];
message = json['message'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['No'] = this.no;
data['interest'] = this.interest;
data['balance'] = this.balance;
data['principal'] = this.principal;
data['Installment'] = this.installment;
data['Status'] = this.status;
data['message'] = this.message;
return data;
}
How to get the value from simulators and showing list view in fetch data? So on another pages just showing in list based on picture 2.
This is my widget build
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: kYellow,
key: _scaffoldKey,
body: Form(
key: _key,
child: Padding(
padding: EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
margin: EdgeInsets.all(20.0),
height: 150.0,
width: 150.0,
child: Image.asset('assets/img/lemonlime.png'),
),
TextFormField(
validator: (value) {
if (value.isEmpty) {
return 'Period time cannot be Empty';
}
return null;
},
onSaved: (value) => periodtime = value,
decoration: kTextFieldDecoration.copyWith(hintText: 'Period time'),
),
SizedBox(
height: 20.0,
),
TextFormField(
validator: (value) {
if (value.isEmpty) {
return 'Interest per month cannot be Empty';
}
return null;
},
onSaved: (value) => interestpermonth = value,
decoration: kTextFieldDecoration.copyWith(hintText: 'Interest Per Month'),
),
SizedBox(
height: 20.0,
),
SizedBox(
height: 20.0,
),
TextFormField(
validator: (value) {
if (value.isEmpty) {
return 'Loan Amount Request cannot be Empty';
}
return null;
},
onSaved: (value) => loanamountrequest = value,
decoration: kTextFieldDecoration.copyWith(hintText: 'Loan Amount Request'),
),
SizedBox(
height: 20.0,
),
FullWidthRoundButton(
textButton: 'Loan Simulation',
getPressed: () {
check();
},
),
],
),
),
),
);
}
And then here is my widget build on simulator.dart
#override
Widget build(BuildContext context) {
timeDilation = 2.0;
return WillPopScope(
onWillPop: () async => false,
child: Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: kYellow,
appBar: AppBar(
leading: Hero(
tag: 'animasilogo',
child: Container(
margin: EdgeInsets.all(5.0),
child: Image.asset('assets/img/lemonlime.png'),
),
),
title: Text('Simulator'),
actions: [
IconButton(
icon: const Icon(Icons.exit_to_app),
onPressed: () {
SharedPref.signOut();
Navigator.pushNamed(context, LoginScreen.id);
},
)
],
),
body: RefreshIndicator(
onRefresh: () => _fetchData(),
child: loading
? Center(child: CircularProgressIndicator())
: ListView.builder(
itemCount: _loanmodel.length,
itemBuilder: (context, index) {
return Container(
alignment: Alignment.topLeft,
margin: const EdgeInsets.only(top: 15.0),
padding: EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Interest : " + _loanmodel[index].interest , style: DefaultTextStyle.of(context).style.apply(fontSizeFactor: 1.5), textAlign: TextAlign.justify),
Text("Balance : " + _loanmodel[index].balance, style: DefaultTextStyle.of(context).style.apply(fontSizeFactor: 1.5),textAlign: TextAlign.justify),
Text("Principal : " + _loanmodel[index].principal, style: DefaultTextStyle.of(context).style.apply(fontSizeFactor: 1.5),textAlign: TextAlign.justify),
Text("Installment :" + _loanmodel[index].installment, style: DefaultTextStyle.of(context).style.apply(fontSizeFactor: 1.5),textAlign: TextAlign.justify),
Divider(
color: Colors.black,
),
],
),
);
},
),
),
),
);
}

Flutter Tried calling: [] error on list builder

I am showing list-builder i need to show just a static data right now I am just check itemCount right now later'll show data but it's showing error .
Here is my code
class _OrderPageState extends State<OrderPage> {
bool showCards = false;
var data;
#override
void initState() {
this.getOrders();
}
getOrders() async{
final storage = new FlutterSecureStorage();
String userId = await storage.read(key: "_userID");
String url =
'http://retailapi.airtechsolutions.pk/api/orders/customer/${userId}/0';
print(url);
http.Response res = await http.get(
url,
);
var data = json.decode(res.body.toString());
print(data);
if(data['description'].toString() == "Success"){
print(data['Orders']);
print(data['Orders'].length); //its printing 6 here
setState(() {
showCards = true;
});}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Order', style: Theme.of(context).textTheme.headline4),
),
body: showCards ? Container(
child: ListView.builder(
itemCount: data['Orders'].length,
shrinkWrap: true,
padding: EdgeInsets.symmetric(horizontal: 18.0, vertical: 20.0),
itemBuilder: (context, index) {
var order = orderList[index];
return SideInAnimation(index, child:GestureDetector(
onTap: () {
// Get.to(OrderDetailPage(order: order));
},
child: Container(
width: double.infinity,
padding: EdgeInsets.all(12.0),
margin: EdgeInsets.only(bottom: 15.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
border: Border.all(color: Theme.of(context).accentColor),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(order.id,
style: Theme.of(context)
.textTheme
.headline3
.copyWith(color: Theme.of(context).primaryColor)),
SizedBox(height: 12.0),
Text(order.dateOrder, style: Theme.of(context).textTheme.subtitle2),
Divider(),
orderCardItem(context,
title: "order.orderstatus", data: order.orderStatus),
SizedBox(height: 12.0),
orderCardItem(context,
title: "order.items",
data: "${order.totalItem} " + tr("order.itemspurchased")),
SizedBox(height: 12.0),
priceItem(context,
title: "order.price", data: "\$ ${order.totalPrice}"),
],
),
),
));
},
),
) : Container(),
);
}
}
In my function its printing the length by in List builder its showing an error that Tried calling: ` But on the print where API load it's showing the length 6.
First you need to initalize a list or array then simply add your data into that variable and then call this variable to your listview builder
var ordersData = [];
then your getData() method should be like this
getOrders() async {
...
if (data['description'].toString() == "Success") {
ordersData.add(data['Orders']); // Add your data to array or list
print(ordersData.length); //its printing 6 here
}
...
}
Here your Listview like this
ListView.builder(
itemCount: ordersData.length, // Here you need to pass this lenght
...
)

Update page data after pop Navigation Updated #5

I have page Navigate to second page with variable (dID) with await to return same value if it has been changed ,at the second page if i did't do anything the value must return without any changes ,if i changed slider the value of (dID) must be increase by (1) ,but when i Navigate.pop the return value is same without increasing.
New update : After many test i did the problem is in the second page ,when i change the slider value i call a function to get the new value (newSavedDayId) ,and it is get it correctly but just inside the function ,after the slider change and get the new value ,it is returned to null :
newSavedDayId = Instance of 'Future<dynamic>'
second page which return value :
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import '../classes/viewdigree.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Days extends StatefulWidget {
#override
_DaysState createState() => _DaysState();
}
TextEditingController insertedDegree = TextEditingController();
class _DaysState extends State<Days> {
#override
Widget build(BuildContext context) {
List digrees = [];
var widthView = MediaQuery.of(context).size.width;
Map rdata = ModalRoute.of(context).settings.arguments;
var did = int.parse(rdata['dayId'].toString());
var u_id = rdata['userID'];
var m_id = rdata['courseId'];
var lang = rdata['lang'];
int w_id;
var newSavedDayId = rdata['savedDayID']; ----// received value
var username;
if (did <= 6) {
w_id = 1;
} else if (did <= 12) {
w_id = 2;
} else if (did <= 18) {
w_id = 3;
} else {
w_id = 4;
}
Future<List> fetchDigrees() async {
var url =
'https://srdtraining.com/api/controller/activities/activiy_list.php?d_id=$did&m_id=$m_id&u_id=$u_id';
var response = await http.get(url);
var data = jsonDecode(response.body);
print(data);
for (var x in data) {
Digree newdigree = Digree(
x['index'],
x['title_k'],
x['title_a'],
x['aya'],
x['link'],
x['activity_k'],
x['activity_a'],
x['act_id'],
x['mydigree']);
digrees.add(newdigree);
}
return digrees;
}
// Insert Func
send_degree(uId, actId, degree, w_id, did, m_id) async {
var sendData = {
'u_id': uId.toString(),
'act_id': actId.toString(),
'digree': degree.toString(),
'm_id': m_id.toString(),
'd_id': did.toString(),
'w_id': w_id.toString()
};
var url = 'https://srdtraining.com/api/controller/data/changedata.php';
var response = await http.post(url, body: sendData);
}
// End of Insert Func
//get user status .................. // this is the function to get new value
void getUserStatus() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
setState(() {
username = preferences.getString('username');
});
var url =
"http://srdtraining.com/api/controller/users/status_user.php?username=$username";
var response = await http.get(url);
var data = jsonDecode(response.body);
setState(() {
newSavedDayId = int.parse(data['d_id']); ----// Set New value by getting it from API after increasing by server.
});
print('newSavedDayId = $newSavedDayId');----// here it is print new value with increasing correctly
}
// End get user
return FutureBuilder(
future: fetchDigrees(),
builder: (context, snapshot) {
if (snapshot.data == null) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('./assets/images/background.png'),
fit: BoxFit.cover)),
child: Center(
child: Text("Loading"),
),
),
);
} else {
YoutubePlayerController _controller = YoutubePlayerController(
initialVideoId: snapshot.data[0].link,
flags: YoutubePlayerFlags(
autoPlay: false,
mute: false,
));
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context, newSavedDayId);
}),
backgroundColor: Colors.pink[900],
title: Text(
'ژیان و قورئان',
style: TextStyle(fontSize: 32),
),
centerTitle: true,
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('./assets/images/background.png'),
fit: BoxFit.cover)),
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: ListView(
padding: EdgeInsets.fromLTRB(25, 20, 25, 20),
shrinkWrap: true,
children: <Widget>[
Text(
lang == 'k'
? snapshot.data[0].title_k
: snapshot.data[0].title_a,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 32, color: Colors.white)),
//for top margin
SizedBox(height: 20.0),
// dexription
Container(
padding: const EdgeInsets.all(15),
width: widthView,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: const Color.fromRGBO(180, 80, 80, 0.3)),
child: Text(snapshot.data[0].aya,
textAlign: TextAlign.justify,
textDirection: TextDirection.rtl,
style: TextStyle(
fontFamily: 'Hafs',
fontSize: 26,
color: Colors.greenAccent[100])),
),
// now populating your ListView for `Directionality`
Column(
children: <Widget>[
// Start activities
Column(
children: snapshot.data.map<Widget>((item) {
double _value =
double.parse(item.mydigree.toString());
return Directionality(
textDirection: TextDirection.rtl,
child: Column(
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
border: Border.all(
width: 2, color: Colors.white),
color:
Color.fromRGBO(230, 200, 200, 0.2)),
width: widthView,
padding: EdgeInsets.all(25),
margin: EdgeInsets.fromLTRB(0, 25, 0, 25),
child: Column(
children: <Widget>[
Text(
lang == 'k'
? item.activity_k
: item.activity_a,
textAlign: TextAlign.justify,
style: TextStyle(
fontSize: 28, color: Colors.white),
),
SizedBox(
height: 15,
),
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.yellow[200]
.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 20,
)
],
borderRadius:
BorderRadius.circular(15),
color:
Color.fromRGBO(0, 0, 0, 0.4)),
width: widthView,
padding: EdgeInsets.all(10),
child: Slider(
max: 100,
min: 0,
divisions: 100,
value: _value,
label: _value.round().toString(),
onChanged: (val) {
send_degree(u_id, item.act_id,
val, w_id, did, m_id);
},
onChangeEnd: (val) {
setState(() {
_value = val;
});
getUserStatus(); /// when i print the value here it is give me null
}),
),
SizedBox(
height: 10,
),
Text('$_value',
style: TextStyle(
fontSize: 26,
color: Colors.white))
],
),
)
],
),
);
}).toList()),
// End activities
SizedBox(
height: 20,
),
Text('خەلەکا ئەڤرو',
textAlign: TextAlign.right,
style:
TextStyle(fontSize: 26, color: Colors.yellow)),
SizedBox(
height: 20,
),
YoutubePlayer(
controller: _controller,
showVideoProgressIndicator: true,
progressIndicatorColor: Colors.blueAccent,
),
],
),
],
),
),
);
}
});
}
}
you can usef ValueChanged onChanged and do a callback to the page you want to update ,
you can passe the onChanged funtion on the parametre ,
when you change your value use : onChanged()
than in the page you want to see the update on call your function with set state ,
I solved it by merging two function in one :
Future<List> fetchDigrees() async {
var url =
'https://srdtraining.com/api/controller/activities/activiy_list.php?d_id=$did&m_id=$m_id&u_id=$u_id';
var response = await http.get(url);
var data = jsonDecode(response.body);
print(data);
for (var x in data) {
Digree newdigree = Digree(
x['index'],
x['title_k'],
x['title_a'],
x['aya'],
x['link'],
x['activity_k'],
x['activity_a'],
x['act_id'],
x['mydigree']);
digrees.add(newdigree);
}
return digrees;
}
void getUserStatus() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
setState(() {
username = preferences.getString('username');
});
var url =
"http://srdtraining.com/api/controller/users/status_user.php?username=$username";
var response = await http.get(url);
var data = jsonDecode(response.body);
setState(() {
newSavedDayId = int.parse(data['d_id']); ----// Set New value by getting it from API after increasing by server.
});
and they now like this and worked correctly :
Future<List> fetchDigrees() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
username = preferences.getString('username');
var url1 =
"http://srdtraining.com/api/controller/users/status_user.php?username=$username";
var response1 = await http.get(url1);
var data1 = jsonDecode(response1.body);
newSavedDayId = int.parse(data1['d_id']);
print('newSavedDayId before retrun = $newSavedDayId');
var url =
'https://srdtraining.com/api/controller/activities/activiy_list.php?d_id=$did&m_id=$m_id&u_id=$u_id';
var response = await http.get(url);
var data = jsonDecode(response.body);
print(data);
for (var x in data) {
Digree newdigree = Digree(
x['index'],
x['title_k'],
x['title_a'],
x['aya'],
x['link'],
x['activity_k'],
x['activity_a'],
x['act_id'],
x['mydigree']);
digrees.add(newdigree);
}
return digrees;
}