select initial value for a Dropdown button in flutter - api

I have searched similar answers to my question but non sufficed mine, Maybe my approach if difficult.
Here is what I'm trying to do,
I have an API for country values.
for registering the user I use a dropdown as below which maps the CountryApi values to its items.
In my hand I have the country name only.
how can I set the initial value of that dropdown to match with the country name I have?
Country Select DropDown
CountryModal _selectedCountry;
onChangeDropdownItem(CountryModel selectedCountry) {
setState(() {
// fieldFocusChange(context, _countryFocusNode, _phoneFocusNode);
_selectedUserCountry = selectedCountry;
_userCountry = _selectedUserCountry.name;
countryCodeTxt = _selectedUserCountry.dial_code;
countryCode = _selectedUserCountry.code;
_userCountryId = _selectedUserCountry.id.toString();
});
}
/////
userCountryDropdown = Container(
padding: EdgeInsets.all(2.0),
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(
10.0,
)),
color: Color(0xFFF0F0F0),
shape: BoxShape.rectangle),
child: DropdownButton<CountryModel>(
isExpanded: true,
hint: Text(
'Select Country',
style: kMainContentStyleLightBlack,
),
autofocus: true,
value: _selectedUserCountry,
isDense: false,
onChanged: onChangeDropdownItem,
items: _countryList.map((country) {
return DropdownMenuItem<CountryModel>(
child: new Text(country.name),
value: country,
);
}).toList(),
style: kMainContentStyleLightBlack,
),
);
My Country API looks in this format
CountryAPI
[
{
"id": 1,
"code": "AF",
"dial_code": "+93",
"name": "افغانستان"
},
{
"id": 2,
"code": "AX",
"dial_code": "+358",
"name": "Åland"
},
....
Can someone help me to figure this out and workaround to resolve?

The value property is what specifies the default selected value for the drop down.
Container(
padding: EdgeInsets.all(2.0),
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(
10.0,
)),
color: Color(0xFFF0F0F0),
shape: BoxShape.rectangle),
child: DropdownButton(
isExpanded: true,
hint: Text(
'Select Country',
style: kMainContentStyleLightBlack,
),
autofocus: true,
value: _selectedUserCountry,
isDense: false,
onChanged: onChangeDropdownItem,
items: _countryList.map((country) {
return DropdownMenuItem(
child: new Text(country.name),
value: country.name,
);
}).toList(),
style: kMainContentStyleLightBlack,
),
);

I didn't read your question much but here is the reference for you. dropdownValue is the default value here
Padding(
padding: EdgeInsets.all(8.0),
child: DropdownButton<String>(
value: dropdownValue,
icon: Icon(Icons.arrow_drop_down),
iconSize: 24,
elevation: 16,
// style: TextStyle(color: Colors.white),
underline: Container(
height: 2,
width: double.infinity,
// color: Colors.deepPurpleAccent,
),
onChanged: (String newValue) {
setState(() {
print(newValue);
dropdownValue = newValue;
});
},
items: <String>['Male', 'Female']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),

Related

Flutter api reloads every navigation

Whenever I change the page and come back, the api is reloaded. I have tried many suggestions. I would be glad if you help.
Here are the methods I tried :
How to avoid reloading data every time navigating to page
How to parse JSON only once in Flutter
Flutter Switching to Tab Reloads Widgets and runs FutureBuilder
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'models/Word.dart';
class WordListPage extends StatefulWidget {
WordListPage(Key k) : super(key: k);
#override
_WordListPageState createState() => _WordListPageState();
}
class _WordListPageState extends State<WordListPage> {
Future<List<Word>> data;
bool isSearching = false;
TextEditingController myController = TextEditingController();
List<Word> _words = List<Word>();
List<Word> _wordsForDisplay = List<Word>();
var keyListPage = PageStorageKey('list_page_key');
Future<List<Word>> getWord() async {
var response = await http.get("myAPIurl");
var _words = List<Word>();
_words = (json.decode(utf8.decode(response.bodyBytes)) as List)
.map((singleWordMap) => Word.fromJsonMap(singleWordMap))
.toList();
return _words;
}
#override
void initState() {
getWord().then((value) {
setState(() {
_words.addAll(value);
_wordsForDisplay = _words;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: myFutureBuilder(),
appBar: AppBar(
leading: Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(
text: 'Total',
style: TextStyle(
decoration: TextDecoration.none,
fontSize: 10,
color: Colors.white,
),
),
TextSpan(
text: '\n${_words.length.toString()}',
style: TextStyle(
decoration: TextDecoration.none,
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 12,
),
),
TextSpan(
text: '\nLetter',
style: TextStyle(
decoration: TextDecoration.none,
color: Colors.white,
fontSize: 10,
),
),
],
),
),
),
centerTitle: true,
title: !isSearching
? Text('My Title')
: TextField(
autofocus: true,
style: TextStyle(color: Colors.white),
controller: myController,
onChanged: (value) {
value = value.toLowerCase();
setState(
() {
_wordsForDisplay = _words.where(
(word) {
var wordTitle = word.word.toLowerCase();
return wordTitle.contains(value);
},
).toList();
},
);
setState(
() {
_wordsForDisplay = _words.where(
(word) {
var wordPronounce = word.pronunciation.toLowerCase();
return wordPronounce.contains(value);
},
).toList();
},
);
},
decoration: InputDecoration(
isCollapsed: true,
icon: Icon(
Icons.menu_book,
color: Colors.white,
),
hintText: 'Search',
hintStyle: TextStyle(color: Colors.white),
),
),
actions: [
isSearching
? IconButton(
icon: Icon(Icons.cancel_outlined),
onPressed: () {
setState(
() {
this.isSearching = false;
myController.clear();
_wordsForDisplay = _words.where(
(word) {
var wordTitle = word.word.toLowerCase();
return wordTitle.contains(wordTitle);
},
).toList();
},
);
},
)
: IconButton(
icon: Icon(Icons.search_sharp),
onPressed: () {
setState(
() {
this.isSearching = true;
},
);
},
),
],
),
);
}
FutureBuilder<List<Word>> myFutureBuilder() {
return FutureBuilder(
future: getWord(),
builder: (context, AsyncSnapshot<List<Word>> snapshot) {
if (snapshot.hasData) {
return myWordListView(snapshot);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
);
}
ListView myWordListView(AsyncSnapshot<List<Word>> snapshot) {
return ListView.builder(
itemCount: _wordsForDisplay.length,
itemBuilder: (context, index) {
return ExpansionTile(
title: Text(
_wordsForDisplay[index].word,
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16.0),
),
subtitle: Text(
snapshot.data[index].pronunciation[0].toUpperCase() +
snapshot.data[index].pronunciation.substring(1),
),
leading: CircleAvatar(
child: Text(snapshot.data[index].word[0]),
),
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 7.0, horizontal: 19.0),
child: RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(
text: snapshot.data[index].word + ' : ',
style: TextStyle(fontWeight: FontWeight.bold),
),
TextSpan(text: snapshot.data[index].meaning),
],
),
),
),
),
],
),
],
);
},
);
}
}
When you navigate and return back, the build method is called. Here you have "myFutureBuilder" placed as the body widget of Scaffold, thus this code get executed, within it "getWord" method is called, an it fetches data from the api everytime.
I suggest you to remove "myFutureBuider" and use "myWirdListView" directly as the body of the scaffold. Change myWordListView(List<Word> listOfWord) to use the word list you have already fetched in the initState() .
You need to to separate your api call from your ui. That way your api will only get called when you want it to. I recommend using some kind of external state management library, such as Provider, BLoC, or RxDart. Flutter will rebuild a widget anytime it wants to, beyond when you trigger it.
you passed getWord() as a function to you future builder so each time the widget get rebuilt, it is called.
To solve that, declare a variable Future<Word> getWordFuture ; , Inside initState assign getWordFuture = getWord(); and use getWordFuture in the Future builder.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'models/Word.dart';
class WordListPage extends StatefulWidget {
WordListPage(Key k) : super(key: k);
#override
_WordListPageState createState() => _WordListPageState();
}
class _WordListPageState extends State<WordListPage> {
Future<List<Word>> data;
bool isSearching = false;
TextEditingController myController = TextEditingController();
List<Word> _words = List<Word>();
List<Word> _wordsForDisplay = List<Word>();
var keyListPage = PageStorageKey('list_page_key');
Future<List<Word>> getWordFuture = Future<List<Word>> ; //1
Future<List<Word>> getWord() async {
var response = await http.get("myAPIurl");
var _words = List<Word>();
_words = (json.decode(utf8.decode(response.bodyBytes)) as List)
.map((singleWordMap) => Word.fromJsonMap(singleWordMap))
.toList();
return _words;
}
#override
void initState() {
getWordFuture = getWord(); //2
getWord().then((value) {
setState(() {
_words.addAll(value);
_wordsForDisplay = _words;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: myFutureBuilder(),
appBar: AppBar(
leading: Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(
text: 'Total',
style: TextStyle(
decoration: TextDecoration.none,
fontSize: 10,
color: Colors.white,
),
),
TextSpan(
text: '\n${_words.length.toString()}',
style: TextStyle(
decoration: TextDecoration.none,
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 12,
),
),
TextSpan(
text: '\nLetter',
style: TextStyle(
decoration: TextDecoration.none,
color: Colors.white,
fontSize: 10,
),
),
],
),
),
),
centerTitle: true,
title: !isSearching
? Text('My Title')
: TextField(
autofocus: true,
style: TextStyle(color: Colors.white),
controller: myController,
onChanged: (value) {
value = value.toLowerCase();
setState(
() {
_wordsForDisplay = _words.where(
(word) {
var wordTitle = word.word.toLowerCase();
return wordTitle.contains(value);
},
).toList();
},
);
setState(
() {
_wordsForDisplay = _words.where(
(word) {
var wordPronounce = word.pronunciation.toLowerCase();
return wordPronounce.contains(value);
},
).toList();
},
);
},
decoration: InputDecoration(
isCollapsed: true,
icon: Icon(
Icons.menu_book,
color: Colors.white,
),
hintText: 'Search',
hintStyle: TextStyle(color: Colors.white),
),
),
actions: [
isSearching
? IconButton(
icon: Icon(Icons.cancel_outlined),
onPressed: () {
setState(
() {
this.isSearching = false;
myController.clear();
_wordsForDisplay = _words.where(
(word) {
var wordTitle = word.word.toLowerCase();
return wordTitle.contains(wordTitle);
},
).toList();
},
);
},
)
: IconButton(
icon: Icon(Icons.search_sharp),
onPressed: () {
setState(
() {
this.isSearching = true;
},
);
},
),
],
),
);
}
FutureBuilder<List<Word>> myFutureBuilder() {
return FutureBuilder(
//future: getWord(),
future:getWordFuture,
builder: (context, AsyncSnapshot<List<Word>> snapshot) {
if (snapshot.hasData) {
return myWordListView(snapshot);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
);
}
ListView myWordListView(AsyncSnapshot<List<Word>> snapshot) {
return ListView.builder(
itemCount: _wordsForDisplay.length,
itemBuilder: (context, index) {
return ExpansionTile(
title: Text(
_wordsForDisplay[index].word,
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16.0),
),
subtitle: Text(
snapshot.data[index].pronunciation[0].toUpperCase() +
snapshot.data[index].pronunciation.substring(1),
),
leading: CircleAvatar(
child: Text(snapshot.data[index].word[0]),
),
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 7.0, horizontal: 19.0),
child: RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(
text: snapshot.data[index].word + ' : ',
style: TextStyle(fontWeight: FontWeight.bold),
),
TextSpan(text: snapshot.data[index].meaning),
],
),
),
),
),
],
),
],
);
},
);
}
}

flutter api image parameter showing null

hello i am new to flutter and i m using update profile api in my profile api i describe all parameter and image base 64 also now what is going on ! suppose alredy is image showing on my profile pic and i never pic image from my camera and device My "Profile Pic" parameter showing null when i call it...! and when i picke image from my device it showing base 64...! what i want is if there is alredy image showing then profile api function i want success because there is alredy image shown ... now u suggest me when i call Profile api function on my Button wht i need to pass
PickedFile _imageFile;
final ImagePicker _picker = ImagePicker();
String img64;
void takePhoto(ImageSource source) async {
final pickedFile = await _picker.getImage(source: source);
setState(() {
_imageFile = pickedFile;
final bytes = Io.File(_imageFile.path).readAsBytesSync();
img64 = base64Encode(bytes);
print(img64.substring(0, 100));
});
}
Profile(String FirstnName,String Lastname,String Email,String DOB,String
Anniversary) async {
sharedPreferences = await SharedPreferences.getInstance();
ValidateCustomer();
Map data =
{
"AccessToken": sharedPreferences.getString("AccessToken"),
"CustomerId": sharedPreferences.getInt("CustomerId"),
"FirstName": FirstnName ,
"LastName": Lastname,
"Email": Email,
"DOB":DOB,
"AnniversaryDate": Anniversary,
"ProfilePicture" : img64
};
print(data);
final http.Response response = await http.post(
Constants.CUSTUMER_WEBSERVICE_UPDATEPROF_URL,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(data),
);
var jsonResponse;
if (response.statusCode == 200)
{
print(sharedPreferences.setString("FirstName", FirstnName));
jsonResponse = json.decode(response.body);
sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString("FirstName", FirstnName);
sharedPreferences.setString("ProfilePicture",img64);
print("Response status : ${response.statusCode}");
print("Response status : ${response.body}");
print(sharedPreferences);
if(jsonResponse != null && ! jsonResponse.containsKey("Error")){
setState(() {
_isLoading = false;
});
print(sharedPreferences);
Navigator.of(context).push(
MaterialPageRoute(builder: (context)=>
ShelfScreen())
);
}
else{
setState(() {
_isLoading = false;
});
print("Response status : ${response.body}");
}
}
if (response.statusCode == 404){
print("Response status : ${response.statusCode}");
print("Response status : ${response.body}");
}
}
Future<UserUpdate>ProfileUpadte() async {
sharedPreferences = await SharedPreferences.getInstance();
ValidateCustomer();
Map data =
{
"AccessToken": sharedPreferences.getString("AccessToken"),
"CustomerId": sharedPreferences.getInt("CustomerId"),
};
print(data);
final http.Response response = await http.post(
"http://api.pgapp.in/v1/userdetails",
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(data),
);
if (response.statusCode == 200)
{
print("Response status : ${response.statusCode}");
print("Response status : ${response.body}");
var jsonResponse = json.decode(response.body);
if(jsonResponse != null && ! jsonResponse.containsKey("Error")){
sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString("ProfilePicture",
jsonResponse["ProfilePicture"]);
sharedPreferences.setString("FirstName", jsonResponse["FirstName"]);
print(sharedPreferences);
}
else{
setState(() {
_isLoading = false;
});
print("Response status : ${response.body}");
}
return UserUpdate.fromJson(json.decode(response.body));
}
else {
// If the server did not return a 201 CREATED response,
// then throw an exception.
throw Exception('Failed to load data');
}
}
void nextField ({String value,FocusNode focusNode}){
if (value.isNotEmpty){
focusNode.requestFocus();
}
}
AnimationController _controller;
Animation _animation;
FocusNode _focusNode1 = FocusNode();
bool _isLoading = false;
String _Firstnm;
String _Lastnm;
String _Mobno;
String _Email;
String _Dob;
String _Anniversary;
DateTime _selectedDate;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
FocusNode Firstname;
FocusNode LastndName;
FocusNode Email;
FocusNode DOB;
FocusNode Anniversary;
Future<UserUpdate> _futureProfileupdate;
#override
void initState() {
// TODO: implement initState
super.initState();
Firstname = FocusNode();
LastndName = FocusNode();
Email = FocusNode();
DOB = FocusNode();
Anniversary = FocusNode();
_futureProfileupdate = ProfileUpadte();
}
void _showPicker(context) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return SafeArea(
child: Container(
child: new Wrap(
children: <Widget>[
new ListTile(
leading: new Icon(Icons.photo_library),
title: new Text('Photo Library'),
onTap: () {
takePhoto(ImageSource.gallery);
Navigator.of(context).pop();
}),
new ListTile(
leading: new Icon(Icons.photo_camera),
title: new Text('Camera'),
onTap: () {
takePhoto(ImageSource.camera);
Navigator.of(context).pop();
},
),
],
),
),
);
}
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
resizeToAvoidBottomPadding: false,
body: (_isLoading) ? Center(child: CircularProgressIndicator()) :
FutureBuilder<UserUpdate>(
future: _futureProfileupdate,
builder: (context, snapshot) {
if (snapshot.hasData) {
TextEditingController _textEditingControllerFirstNamee =
TextEditingController(text: snapshot.data.firstName);
TextEditingController _textEditingControllerLastnamee = TextEditingController(text: snapshot.data.lastName);
TextEditingController _textEditingControllerEmaill = TextEditingController(text: snapshot.data.email);
TextEditingController _textEditingControllerDOBb = TextEditingController(text: snapshot.data.dob);
TextEditingController _textEditingControllerAnniversaryy = TextEditingController(text: snapshot.data.anniversaryDate);
_selectDate(BuildContext context) async {
DateTime newSelectedDate = await showDatePicker(
context: context,
initialDate: _selectedDate != null ? _selectedDate : DateTime.now(),
firstDate: DateTime(1920),
lastDate: DateTime(2040),
builder: (BuildContext context, Widget child) {
return Theme(
data: ThemeData.dark().copyWith(
colorScheme: ColorScheme.dark(
primary: Colors.deepPurple,
onPrimary: Colors.white,
surface: Colors.blueGrey,
onSurface: Colors.yellow,
),
dialogBackgroundColor: Colors.blue[500],
),
child: child,
);
});
if (newSelectedDate != null) {
_selectedDate = newSelectedDate;
_textEditingControllerDOBb
..text = DateFormat.yMMMd().format(_selectedDate)
..selection = TextSelection.fromPosition(TextPosition(
offset: _textEditingControllerDOBb.text.length,
affinity: TextAffinity.upstream));
}
}
_selectDate2(BuildContext context) async {
DateTime newSelectedDate = await showDatePicker(
context: context,
initialDate: _selectedDate != null ? _selectedDate : DateTime.now(),
firstDate: DateTime(1920),
lastDate: DateTime(2040),
builder: (BuildContext context, Widget child) {
return Theme(
data: ThemeData.dark().copyWith(
colorScheme: ColorScheme.dark(
primary: Colors.deepPurple,
onPrimary: Colors.white,
surface: Colors.blueGrey,
onSurface: Colors.yellow,
),
dialogBackgroundColor: Colors.blue[500],
),
child: child,
);
});
if (newSelectedDate != null) {
_selectedDate = newSelectedDate;
_textEditingControllerAnniversaryy
..text = DateFormat.yMMMd().format(_selectedDate)
..selection = TextSelection.fromPosition(TextPosition(
offset: _textEditingControllerAnniversaryy.text.length,
affinity: TextAffinity.upstream));
}
}
return Form(
key: _formKey,
child: Stack(
children: <Widget>[
Positioned(
left: 20,
top: 40,
child: Center(
child: Image.asset(
'assets/images/logo.png', height: 50, width: 50,),
)
),
Positioned(
left: 60,
right: 60,
top: 40,
child: Center(
child: Image.asset(
'assets/images/Textimage.png', height: 50,
width: 170,),
)
),
Positioned(
right: 20,
top: 40,
child: Center(
child: IconButton(
icon: Icon(Icons.exit_to_app, size: 30,
color: Color(0xfff58634),),
onPressed: () async {
showAboutDialog(context);
},
)
)
),
Positioned(
left: 70,
right: 70,
top: 110,
child: Center(
child: CircleAvatar(
backgroundImage: _imageFile == null ? NetworkImage(
snapshot.data.profilePicture) : FileImage(Io.File(_imageFile.path)),
backgroundColor: Colors.grey,
maxRadius: 50,
)
)
),
Positioned(
left: 100,
right: 70,
top: 170,
child: InkWell(
onTap: (){
_showPicker(context);
},
child: Icon(
Icons.camera_alt,
color: Colors.white,
size: 30,
),
),
),
Positioned(
left: 30,
right: 30,
top: 250,
child: Container(
height: 480,
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 5),
child: SizedBox(
height: 70,
child: TextFormField(
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.sentences,
textInputAction: TextInputAction.next,
focusNode: Firstname,
onFieldSubmitted: (value) {
nextField(
value: value, focusNode: LastndName);
},
controller: _textEditingControllerFirstNamee,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(
5.0),
borderSide: BorderSide(
color: const Color(0x3df58634)
)
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(
5.0)
),
labelText: "First Name",
labelStyle: GoogleFonts.nunito(
color: const Color(0xfff58634)),
hintText: "First Name",
hintStyle: GoogleFonts.nunito(
color: const Color(0xfff58634)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(
5.0),
borderSide: BorderSide(
color: const Color(0x3df58634),
)
),
),
validator: (String value) {
if (value.isEmpty) {
return 'First Name is Required';
}
return null;
},
onSaved: (String value) {
_Firstnm = value;
},
),
),
),
Padding(
padding: const EdgeInsets.only(top: 5),
child: SizedBox(
height: 70,
child: TextFormField(
keyboardType: TextInputType.text,
textCapitalization:
TextCapitalization.sentences,
focusNode: LastndName,
textInputAction: TextInputAction.next,
onFieldSubmitted: (value) {
nextField(value: value, focusNode:
Email);
},
controller:
_textEditingControllerLastnamee,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(
5.0),
borderSide: BorderSide(
color: const Color(0x3df58634)
)
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(
5.0)
),
labelText: 'Last Name',
labelStyle: GoogleFonts.nunito(
color: const Color(0xfff58634)),
hintText: "Last Name",
hintStyle: GoogleFonts.nunito(
color: const Color(0xfff58634)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(
5.0),
borderSide: BorderSide(
color: const Color(0x3df58634),
)
),
),
validator: (String value) {
if (value.isEmpty) {
return 'First Name is Required';
}
return null;
},
onSaved: (String value) {
_Lastnm = value;
},
),
),
),
Padding(
padding: const EdgeInsets.only(top: 5),
child: SizedBox(
height: 70,
child: TextFormField(
focusNode: Email,
textInputAction: TextInputAction.next,
onFieldSubmitted: (value) {
nextField(value: value, focusNode: DOB);
},
controller: _textEditingControllerEmaill,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(
5.0),
borderSide: BorderSide(
color: const Color(0x3df58634)
)
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(
5.0)
),
labelText: 'Email',
labelStyle: GoogleFonts.nunito(
color: const Color(0xfff58634)),
hintText: "Email",
hintStyle: GoogleFonts.nunito(
color: const Color(0xfff58634)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(
5.0),
borderSide: BorderSide(
color: const Color(0x3df58634),
)
),
),
validator: (value) => EmailValidator.validate(value) ? null : "Please enter a valid email",
onSaved: (String value) {
_Email = value;
},
),
),
),
Padding(
padding: EdgeInsets.only(top: 45),
child: SizedBox(
width: 360,
height: 45,
child: RaisedButton(
onPressed: () {
if (!_formKey.currentState.validate()) {
return;
}
setState(() {
_isLoading = true;
});
Profile(
_textEditingControllerFirstNamee.text,
_textEditingControllerLastnamee.text,
_textEditingControllerEmaill.text,
_textEditingControllerDOBb.text,
_textEditingControllerAnniversaryy
.text,);
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ShelfScreen()));
},
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(
5.0)),
color: const Color(0xfff58634),
child: Text(
"Update",
style: GoogleFonts.nunito(
color: const Color(0xffffffff),
fontSize: 20
),
),
),
),
),
Padding(
padding: EdgeInsets.only(top: 120),
child: Text(".", style: TextStyle(
color: Colors.transparent, fontSize: 1,
),),
)
],
),
),
),
),
],
),
);
} else {
return CircularProgressIndicator();
);
}
}
)
);
}
}
class AlwaysDisabledFocusNode extends FocusNode {
#override
bool get hasFocus => false;
}

How to get ListView builder data using api response in flutter ui using provider

Im trying to get an response from provider and fetching in a ui page but when i try to add an response to ui it shows an error
The getter 'data' was called on null. Receiver: null Tried calling: data
In this Line:
ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: doctorList.data.length,
primary: true,
is this is correct approuch or need to change modal class or ui integration.
im accessing data through doctorList.data.->datas data.
My response modal class.
import 'dart:convert';
Doctorlist doctorlistFromJson(String str) => Doctorlist.fromJson(json.decode(str));
String doctorlistToJson(Doctorlist data) => json.encode(data.toJson());
class Doctorlist {
Doctorlist({
this.status,
this.message,
this.data,
});
int status;
String message;
List<Datum> data;
factory Doctorlist.fromJson(Map<String, dynamic> json) => Doctorlist(
status: json["status"],
message: json["message"],
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"status": status,
"message": message,
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class Datum {
Datum({
this.id,
this.mobile,
this.userImage,
this.emrNumber,
this.hospital,
this.status,
this.doctorName,
this.docRole,
this.email,
this.gender,
this.address,
this.city,
this.state,
this.pincode,
this.clinicName,
this.appointmentDate,
this.favourite,
});
String id;
String mobile;
String userImage;
String emrNumber;
String hospital;
String status;
String doctorName;
String docRole;
String email;
String gender;
String address;
String city;
String state;
String pincode;
String clinicName;
DateTime appointmentDate;
String favourite;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
id: json["id"],
mobile: json["mobile"],
userImage: json["user_image"],
no: json["no"],
hospital: json["hospital"],
status: json["status"],
doctorName: json["doctor_name"],
docRole: json["doc_role"],
email: json["email"],
gender: json["gender"],
address: json["address"],
city: json["city"],
state: json["state"],
pincode: json["pincode"],
clinicName: json["clinic_name"],
appointmentDate: DateTime.parse(json["appointment_date"]),
favourite: json["favourite"],
);
Map<String, dynamic> toJson() => {
"id": id,
"mobile": mobile,
"user_image": userImage,
"emr_number": emrNumber,
"hospital": hospital,
"status": status,
"doctor_name": doctorName,
"doc_role": docRole,
"email": email,
"gender": gender,
"address": address,
"city": city,
"state": state,
"pincode": pincode,
"clinic_name": clinicName,
"appointment_date": "${appointmentDate.year.toString().padLeft(4, '0')}-${appointmentDate.month.toString().padLeft(2, '0')}-${appointmentDate.day.toString().padLeft(2, '0')}",
"favourite": favourite,
};
}
My Provider class:
class DoctorListProvider extends ChangeNotifier {
Doctorlist doctorList;
Future<Doctorlist> doctorlist() async {
try {
final response = await http.post(
(Commons.baseURL + "/list"),
headers: {
"Accept": "application/json",
"content-type": "application/json",
},body:{"id":5});
if (response.statusCode == 200) {
var responseJson = Commons.returnResponse(response);
doctorList = Doctorlist.fromJson(responseJson);
print(doctorList);
return Doctorlist.fromJson(responseJson);
} else {
return null;
}
} on SocketException {
return null;
}
}
}
my ui List View builder page :
class _DoctorState extends State<Doctor> {
Doctorlist doctorList;
bool fav = true;
#override
void initState() {
doctorList =
Provider.of<DoctorListProvider>(context, listen: false).doctorList;
super.initState();
}
#override
Widget build(BuildContext context) {
ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: doctorList.data.length,
// itemCount: 2,
// reverse: false,
primary: true,
itemBuilder: (BuildContext context, int index) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
child: Flexible(
child:
Container(child:
InkWell(
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => Doctordetails()));
},
child:
Card(
// color: Color(0xff29ABE2),
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: 100,
),
child: Padding(
padding: EdgeInsets.only(
left: 10,
right: 0,
top: 10),
child: Row(
children: <Widget>[
Column(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: <Widget>[
Row(
mainAxisAlignment:
MainAxisAlignment
.start,
crossAxisAlignment:
CrossAxisAlignment
.start,
children: <
Widget>[
Container(
decoration:
new BoxDecoration(
borderRadius:
BorderRadius.all(
const Radius.circular(100.0)),
border: Border.all(
color: Colors
.black),
),
height: 70,
width: 70,
child:
ClipRRect(
borderRadius:
BorderRadius.circular(
200),
child: Image
.asset(
'assets/images/registration/profile_side.png',
fit: BoxFit
.fill,
),
),
),
SizedBox(
width: MediaQuery.of(
context)
.size
.height /
80,
),
Column(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: <
Widget>[
Text(
"no",
style: TextStyle(
fontFamily:
"SansBold",
fontSize:
15,
color:
Colors.black),
),
Text(
"no",
style: TextStyle(
fontFamily:
"SansRegular",
fontSize:
15,
color:
Colors.black),
),
SizedBox(
height: 5,
),
SizedBox(
height: MediaQuery.of(context)
.size
.height /
13,
width: MediaQuery.of(context)
.size
.width /
1.9,
child:
AutoSizeText(
'no ',
style: TextStyle(
fontSize:
20),
maxLines:
3,
),
)
],
),
Container(
child:
IconButton(
onPressed:
() {
setState(
() {
fav =
!fav;
});
},
icon: fav
? Image.asset(
"assets/images/appointment/favourite_unselected.png")
: Image.asset(
"assets/images/appointment/favourite_select.png"),
))
],
),
SizedBox(
height: 5,
),
Row(
children: <
Widget>[
Container(
child: IconButton(
icon: Image
.asset(
"assets/images/appointment/last_appointment.png"),
onPressed:
null),
),
SizedBox(
width: 10,
),
Text(
"Last appointment date",
style: TextStyle(
fontFamily:
"SansRegular",
fontSize:
15,
color: Colors
.black),
)
],
),
Container(
child: Text(
"06-08-2020"),
),
],
),
SizedBox(
width: MediaQuery.of(
context)
.size
.width /
40,
),
],
))))))))
],
);
},
),
My Json response Look Like this.
{
"status": 1,
"message": "success",
"data": [
{
"id": "1",
"mobile": "7",
"user_image": "https://hghjfjd.com",
"emr_number": "er-357",
"hospital": "ff",
"status": "1",
"doctor_name": "sanje",
"doc_role": "dfd",
"email": "doctor#gmail.com",
"gender": "Male",
"address": "test mode",
"city": "england",
"state": "tn",
"pincode": "633211",
"clinic_name": "clinic",
"appointment_date": "2020-09-07",
"favourite": "No"
},
Try this:
): Edit initState() method to:
#override
void initState(){
WidgetsBinding.instance.addPostFrameCallback((_) => _afterLayout(context));
}
): Now you can load items in _afterLayout(context) method:
_afterLayout(BuildContext context) async {
var docState = Provider.of<DoctorListProvider>(context);
docState.setDoctorList(await docState.doctorlist());
}
): Update this class DoctorListProvider :
class DoctorListProvider extends ChangeNotifier {
Doctorlist _doctorList;
Doctorlist get getDoctorList => _doctorList;
set setDoctorList(Doctorlist input){
_doctorList = input;
notifierListners();
}
...
}
): Finally use this in you UI :
class _DoctorState extends State<Doctor> {
bool fav = true;
#override
void initState(){
WidgetsBinding.instance.addPostFrameCallback((_) => _afterLayout(context));
}
#override
Widget build(BuildContext context) {
var docState = Provider.of<DoctorListProvider>(context);
return docState.getDoctorList == null ? Container(child: CircularProgressIndicator()) :
ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: docState.getDoctorList.data.length,
// itemCount: 2,
// reverse: false,
primary: true,
itemBuilder: (BuildContext context, int index) {
How I handled that error was that I eradicated or gave "" to the null value.
It's because the data that you are fetting from your API response has a null value.
If you know which value might be null you can assign an empty String value and will solve the error.
Here are the codes of how I did it. It's not professional but it gets your work done.

how to navigate to other page from streambuilder in flutter?

i am trying to implement login functionality using bloc pattern in flutter. So I want to navigate to main page after authentication is successful. from loginBloc.dart I will get the status inside the streamBuilder in login.dart when the status is success I want to navigate to main.dart but I cant able to understand how to call the main.dart inside the streamBuilder in login.dart.
login.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_svg/svg.dart';
import 'package:hotelorders/bloc/LoginBloc.dart';
import 'package:hotelorders/screens/Home.dart';
class Login extends StatefulWidget
{
#override
State<StatefulWidget> createState() {
return LoginState();
}
}
class LoginState extends State<Login>
{
final LoginBloc _loginBloc = LoginBloc();
String _email,_password;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
#override
void dispose()
{
_loginBloc.dispose();
super.dispose();
}
Widget _progressBar()
{
return StreamBuilder<bool>(
stream: _loginBloc.progressStream,
builder: (BuildContext context,AsyncSnapshot<bool> snapShot) {
bool visible;
if(snapShot.data == null)
{
visible = false;
}
else
{
visible = snapShot.data;
}
return Visibility(
maintainSize: true,
maintainAnimation: true,
maintainState: true,
visible: visible,
child: Container(
child: Center(
child: SizedBox(
width: 60,
height: 60,
child: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(0.0, 1.0), //(x,y)
blurRadius: 1.0,
),
],
),
),
Center(
child: CircularProgressIndicator(),
)
],
),
)
)
),
);
}
);
}
Widget _emailTextField()
{
return TextFormField(
decoration: InputDecoration(
labelText: "Email id",
border: OutlineInputBorder(
borderRadius: new BorderRadius.circular(32.0),
)
),
keyboardType: TextInputType.emailAddress,
validator: (String value){
if(value.isEmpty || !RegExp(r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?").hasMatch(value))
{
return "Enter a valid email id";
}
return null;
},
onSaved: (String value){
_email = value;
},
);
}
Widget _passwordTextField()
{
return TextFormField(
decoration: InputDecoration(labelText: "Password",
filled: true,
border: OutlineInputBorder(
borderRadius: new BorderRadius.circular(32.0),
),
fillColor: Colors.white
),
keyboardType: TextInputType.text,
obscureText: true,
validator: (String value){
if(value.isEmpty)
{
return "Enter a valid password";
}
else if(value.length < 8)
{
return "Password is too short";
}
else
{
return null;
}
},
);
}
void _login()
{
if(!_formKey.currentState.validate())
{
return;
}
_formKey.currentState.save();
Map<String,String> map = new Map();
map['email'] = _email;
map['password'] = _password;
_loginBloc.login(map);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Container(
alignment: Alignment.center,
margin: EdgeInsets.fromLTRB(0, 48, 0, 0),
child: Text(
"Take Orders and",
style: TextStyle(color: Theme.of(context).primaryColorDark,fontSize: 20),
),
),
Container(
child: Text(
"Track the Best Selling Items",
style: TextStyle(color: Theme.of(context).primaryColor,fontSize: 16),
),
),
Container(
margin: EdgeInsets.fromLTRB(16, 0, 16, 0),
child: SvgPicture.asset('assets/images/undraw_booking.svg',width: 100.0,height: 280.0,),
),
Container(
margin: EdgeInsets.fromLTRB(16, 0, 0, 0),
child:Row(
children: <Widget>[
Text(
"Login To ",
style: TextStyle(color: Colors.black,fontSize: 20)
),
Text(
"Take orders",
style: TextStyle(color: Theme.of(context).primaryColorDark,fontSize: 20),
)
],
),
),
Container(
margin: EdgeInsets.fromLTRB(16, 8, 16, 0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.fromLTRB(0, 8, 0, 0),
child: _emailTextField(),
),
Container(
margin: EdgeInsets.fromLTRB(0, 8, 0, 0),
child: _passwordTextField(),
),
Container(
margin: EdgeInsets.fromLTRB(0, 8, 0, 0),
child: Align(
alignment: Alignment.centerLeft,
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(32.0)
),
padding: EdgeInsets.fromLTRB(64, 12, 64, 12),
color: Theme.of(context).accentColor,
textColor: Colors.white,
child: Text(
"Login",
),
onPressed: (){
_login();
},
) ,
),
),
StreamBuilder<dynamic>(
stream:_loginBloc.loginStateStream,
builder: (BuildContext context, AsyncSnapshot<dynamic> snapShot){
if(snapShot.data == "success")
{
// WidgetsBinding.instance.addPostFrameCallback((_){
// Navigator.push(context, MaterialPageRoute(
// builder: (context)=> Home()
// ));
// });
}
else if(snapShot.data != null && snapShot.data != "success")
{
WidgetsBinding.instance.addPostFrameCallback((_) {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('${snapShot.data}',
style: TextStyle(color: Colors.black),),
backgroundColor: Color(0xFFe5e5e5),
));
// showDialog(context: context,builder: (BuildContext con){
// return AlertDialog(
// title: Text('${snapShot.data}'),
// );
// });
});
}
return Container();
},
)
],
),
),
)
],
),
)
),
_progressBar(),
],
),
);
}
}
LoginBloc.dart
import 'dart:async';
class LoginBloc
{
// here event comes in and state goes out
//stream conntroller for output
final _loginStateController = StreamController<String>();
//stream controller for input
final _loginEventController = StreamController<Map<String,String>>();
final _progressController = StreamController<bool>();
StreamSink<String> get loginStateSink => _loginStateController.sink;
Stream<String> get loginStateStream => _loginStateController.stream;
Sink<Map<String,String>> get loginEventSink => _loginEventController.sink;
Stream<bool> get progressStream => _progressController.stream;
StreamSink<bool> get progressSink => _progressController.sink;
LoginBloc()
{
progressSink.add(false);
_loginEventController.stream.listen(login);
}
login(Map<String,String> loginDetails)
{
progressSink.add(true);
Timer(Duration(seconds: 3), () {
progressSink.add(false);
loginStateSink.add("success");
});
// when we pass data in sink we get the output from stream
}
void dispose()
{
_loginEventController.close();
_loginStateController.close();
_progressController.close();
}
}
You are almost there. The following should work :
if(snapShot.data == "success")
{
Navigator.push(
context, MaterialPageRoute(builder: (context)=> Home()));
}
Note : WidgetsBinding.instance.addPostFrameCallback is used to get a callback when widget tree is loaded.

Flutter input decoration suffixIcon not appearing but always showing cross symbol

I have the following example codes. I have now managed to put the prefixicon and it works fine. I want to move the same icon the suffix meaning on the right hand side but it just does not work but the X symbol it what appears.
Here is a screen shot.
I have added the following lines suffixIcon: IconButton( but it seems not be appearing but the one on the left hand side which is the prefix appears perfectly fine. I cant get the one on the right hand side. What is blocking it from appearing?
Below is my codes.
class MyHomePageState extends State<MyHomePage> {
// Show some different formats.
final formats = {
//InputType.both: DateFormat("EEEE, MMMM d, yyyy 'at' h:mma"),
//InputType.date: DateFormat('dd/MM/yyyy'),
//InputType.time: DateFormat("HH:mm"),
InputType.date: DateFormat("d MMMM yyyy"),
};
//InputType.date: DateFormat('yyyy-MM-dd'),
// Changeable in demo
InputType inputType = InputType.date;
bool editable = true;
DateTime date;
#override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: Text(appName)),
body: Padding(
padding: EdgeInsets.all(16.0),
child: ListView(
children: <Widget>[
Form(
//key: _myKey,
child: Column(
children : [
new Container(
width: 200.0,
child:new DateTimePickerFormField(
dateOnly: true,
format: formats[inputType],
editable: false,
validator: (val) {
if (val != null) {
return null;
} else {
return 'Date Field is Empty';
}
},
/*decoration: InputDecoration(
border: InputBorder.none,
labelText: 'From',contentPadding: const EdgeInsets.symmetric(horizontal: 20.0)),*/
decoration: InputDecoration(
hintText: 'To',
border: InputBorder.none,
filled: false,
prefixIcon: Icon(
Icons.arrow_drop_down,
color: Colors.blue,
size: 28.0,
),
suffixIcon: IconButton(
icon: Icon(Icons.arrow_drop_down,size: 28),
onPressed: () {
debugPrint('222');
})),
initialValue: DateTime.now().subtract(new Duration(days: 7)), //Add this in your Code.
),
)
]
),
),
RaisedButton(
onPressed: () {
/*if (_myKey.currentState.validate()) {
_myKey.currentState.save();
} else {
}*/ print("check;");
if(emailController.text.isEmpty){
print("TEST;");
//valid = false;
//emailError = "Email can't be blank!";
//openAlertBox();
Toast.show("Empty Date From", context, backgroundColor: Colors.red );
}
else{
print("not empty;");
final f = new DateFormat('yyyy-MM-dd');
final original = new DateFormat('d MMMM yyyy');
print("Format datre is"+emailController.text);
print("Formate date :"+original.parse(emailController.text).toString());
}
},
child: Text('Submit'),
)
],
),
));
I re-created your case by singling out only the TextFormField code you provided and was able to see the dropdown arrow as suffixIcon.
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
height: MediaQuery
.of(context)
.size
.height,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children : [
new Container(
color: Colors.yellow,
width: 200.0,
child: TextFormField(
decoration: InputDecoration(
hintText: 'To',
border: InputBorder.none,
filled: false,
prefixIcon: Icon(
Icons.arrow_drop_down,
color: Colors.blue,
size: 28.0,
),
suffixIcon: IconButton(
icon: Icon(Icons.arrow_drop_down,size: 28),
onPressed: () {
debugPrint('222');
})),
),
)
]
)
),
)
);
}
}
I see that you used Padding as your body to return Scaffold. Try to replace it with Center or Container
You may have discovered the following but posting just in case...
The 'X' displayed is the reset icon for the date field ie. you use that to clear the field. You can turn it off with DateTimePickerFormField property 'resetIcon: null;' but then the only way to remove a date from the field is to ensure 'editable: true', which is the default but you have overridden it in your code.
Hope that helps.