Related
I have a dart page voterhome(like dashboard),at first when I arrive at voterhome it will call the getuserdetails() function and get the adhar of user to pass it to other pages so I can navigate to other pages (like vote,voteregister ..etc)
when I return back to voterhome from other pages it will call the getuserdetails()function again because the function is inside initstate() I don't want this to happen how can I do that
my code :
voterhome.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:election/services/IntoLogin.dart';
import 'package:election/pages/Voter/Vote.dart';
import 'package:election/pages/Voter/VoteRegister.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:web3dart/web3dart.dart';
import '../../services/Auth.dart';
import '../../utils/Constants.dart';
import '../../services/Electioninfo.dart';
import '../../services/VerifyEmail.dart';
class VoterHome extends StatefulWidget {
//getting required parameters to pass on to vote and authorize
final Web3Client ethClient;
final String electionName;
final String electionaddress;
const VoterHome({Key? key, required this.ethClient, required this.electionName, required this.electionaddress}) : super(key: key);
#override
State<VoterHome> createState() => _VoterHomeState();
}
class _VoterHomeState extends State<VoterHome> {
//creating clients
late Client? httpClient;//http client
late Web3Client? ethclient;// eth client
//sign out user
final User? user = Auth().currentuser;
Future<void>signOut()async{
await Auth().signOut();
if(!mounted)return;
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (context)=>IntroLogin()), (route) => false);
}
// voters info
var email;
var adhar;
var name;
var phone;
//checking if voter authorized or voted // dont have to do this because we does this on the respected pages
late bool isAuth = false;//if he is authorized
late bool isVoted = false;//if he is voted
Future<void>getUserDetail() async {
try {
final DocumentSnapshot voters = await FirebaseFirestore.instance
.collection('voters')
.doc(user?.email)
.get();
if (voters.data() != null) {
email = voters.get('email');
name = voters.get('name');
phone = voters.get('phone');
adhar = voters.get('adharnum');
print('adhar is $adhar');
}else{
print('cannot find details');
}
showSnackBar(succesdetailsnackSnack);
} catch (e) {
if (kDebugMode) {
print('get check user ::::: $e');
showSnackBar(errordetailsnackSnack);
}
}
}//function to check ends
#override
void initState() {
httpClient = Client();
ethclient = Web3Client(infura_url, httpClient!);
WidgetsBinding.instance.addPostFrameCallback((_) async {
await getUserDetail();
setState(() { });
});
super.initState();
}
#override
Widget build(BuildContext context) {
Map<String,dynamic> voterdata = {'name':name,'adharnum':adhar.toString(),'email':email,};
if(user!.emailVerified){
return Scaffold(
appBar: AppBar(
leading: IconButton(onPressed: () { signOut(); }, icon: const Icon(Icons.logout),),
actions: [IconButton(onPressed:(){setState(() {});}, icon: const Icon(Icons.refresh))],
title: const Text('Voter DASHBOARD'),backgroundColor: Colors.cyan,),
body: SingleChildScrollView(
child: Column(
children: [
Container(
padding: const EdgeInsets.all(24),
margin: const EdgeInsets.only(bottom: 16),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => VoteRegister(electionName:widget.electionName,
ethClient: widget.ethClient, electionaddress:widget.electionaddress,adhar:adhar,)));
},
child: Card(borderOnForeground: true,elevation: 4,
child: Column(
children: [
Container(height: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
image: const DecorationImage(
image: AssetImage('assets/undraw/electionday.png')))),
Container(decoration: const BoxDecoration(color: Colors.cyan),width: double.infinity,
child: const Center(
child: Text('Register to Vote',style: TextStyle(
fontWeight: FontWeight.bold,fontSize:16,color: Colors.white),),
),
)
],
),
),
),
),
Container(
padding: const EdgeInsets.all(24),
margin: const EdgeInsets.only(bottom: 16),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => VoterVote(ethClient:ethclient!,electionName:widget.electionName,
electionaddress:widget.electionaddress ,votermap:voterdata,)));
},
child: Card(borderOnForeground: true,elevation: 4,
child: Column(
children: [
Container(height: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
image: const DecorationImage(
image: AssetImage('assets/undraw/upvote.png')))),
Container(decoration: const BoxDecoration(color: Colors.cyan),width: double.infinity,
child: const Center(
child: Text('Vote',style: TextStyle(fontWeight: FontWeight.bold,fontSize:16,color: Colors.white),),
),
)
],
),
),
),
),
Container(
padding: const EdgeInsets.all(24),
margin: const EdgeInsets.only(bottom: 16),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ElectionInfo(ethClient:ethclient!,electionName:widget.electionName,
electionAddress:widget.electionaddress,)));
},
child: Card(borderOnForeground: true,elevation: 4,
child: Column(
children: [
Container(height: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
image: const DecorationImage(
image: AssetImage('assets/undraw/electionday.png')))),
Container(decoration: const BoxDecoration(color: Colors.cyan),width: double.infinity,
child: const Center(
child: Text('Election details',style: TextStyle(
fontWeight: FontWeight.bold,fontSize:16,color: Colors.white),),
),
)
],
),
),
),
),
],
),
)
);
}else{
return Scaffold(
appBar:AppBar( ///app bar
backgroundColor: Colors.cyan,
leading: IconButton(
onPressed: () {
signOut();
},
icon: const Icon(Icons.logout_sharp),
),
title: const Text('Verify Voter email'),
actions: [
IconButton(
onPressed: () {
refresh();
},
icon: const Icon(Icons.refresh))
],
),
body: Container(margin: const EdgeInsets.only(top: 56),
child: Center(
child: Column(
children: [
Text('Your Email ${user?.email} is not verified'),
const SizedBox(height: 24,),
ElevatedButton(
onPressed: () {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => const VerifyEmail()),
(route) => false);
},
child: const Text('Verify Email'))
],
),
),
),
);
}
}
//function to refresh using setstate
void refresh() {
setState(() {});
}
//snackbar
SnackBar errordetailsnackSnack = const SnackBar(content: Text('You are not logged in if you are please check your internet connection'));
SnackBar succesdetailsnackSnack = const SnackBar(content: Text('successfull'));
SnackBar votedSnack = const SnackBar(content: Text('You have already voted'));
SnackBar RegisterSnack = const SnackBar(content: Text('You have already registered'));
// SnackBar errorSnack = const SnackBar(content: Text('Fill all the details'));
// SnackBar datanullSnack = const SnackBar(content: Text('No users registerd yet'));
//function to show snackbar
ScaffoldFeatureController<SnackBar, SnackBarClosedReason> showSnackBar(SnackBar snackBar) {
return ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
}
vote.dart //when i go to voterhome() from this it again calls the function
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:election/pages/Voter/VoterHome.dart';
import 'package:election/utils/Constants.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:web3dart/web3dart.dart';
import '../../services/Auth.dart';
import '../../services/functions.dart';
import '../../services/IntoLogin.dart';
class VoterVote extends StatefulWidget {
final Web3Client ethClient;
final String electionName;
final String electionaddress;
final votermap;
const VoterVote({Key? key, required this.ethClient, required this.electionName, required this.electionaddress, this.votermap,}) : super(key: key);
#override
State<VoterVote> createState() => _VoterVoteState();
}
class _VoterVoteState extends State<VoterVote> {
final User? user = Auth().currentuser;//fi// rebase auth current user initialization
//sign out user function
Future<void> signOut() async {
if (!mounted) return;
await Auth().signOut();
if (!mounted) return;
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => IntroLogin()),
(route) => false);
}
//checking if the voter is already voted
late bool isAuth = false;
late bool isVoted = false;
Future<void>getUserDetail() async {
var voterdetails = widget.votermap;
try {
final DocumentSnapshot voters = await FirebaseFirestore.instance
.collection('Election')
.doc(widget.electionName).collection('voterAuth').doc(voterdetails['adharnum'])
.get();
if (voters.data() != null) {
isAuth = voters.get('isAuth');
isVoted = voters.get('isVoted');
}else{
isAuth = false;
isVoted= false;
print('cannot find details');
}
} catch (e) {
if (kDebugMode) {
print('get check user ::::: $e');
}
}
}//function to check ends
TextEditingController privatekeyController = TextEditingController();
#override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) async {
await getUserDetail();
setState(() { });
});
super.initState();
}
#override
Widget build(BuildContext context) {
if(isVoted== true && isAuth == true){
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.cyan,
leading: IconButton(onPressed: (){signOut();},icon: const Icon(Icons.logout_sharp),),
title:const Text('Vote'),
actions: [
IconButton(onPressed:(){
refresh();
}, icon: const Icon(Icons.refresh))
],
),
body: const Center(child: Text('you have already voted sir'),),
);
}else if(isVoted == false&&isAuth == true){
return Scaffold(
appBar:AppBar(
backgroundColor: Colors.cyan,
leading: IconButton(onPressed: (){signOut();},icon: const Icon(Icons.logout_sharp),),
title:const Text('Vote'),
actions: [
IconButton(onPressed:(){
refresh();
}, icon: const Icon(Icons.refresh))
],
),
body: Container(margin:const EdgeInsets.only(bottom: 56,top: 24),alignment: Alignment.topCenter,
child:SingleChildScrollView(
child: Column(
children: [
Center(
child: SelectableText("$voter_private_key && $voter_key2 && $voter_key3")
),
const SizedBox(height: 24,),
Container(padding: const EdgeInsets.all(16),
child: TextField(
controller: privatekeyController,
decoration:
const InputDecoration(hintText: 'Private key for voting',border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(8))))),
),
const SizedBox(height: 24,),
SingleChildScrollView(
child: StreamBuilder<List>(stream:getCandidatesNum(widget.ethClient,widget.electionaddress).asStream(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
return Column(
children: [
for (int i = 0; i < snapshot.data![0].toInt(); i++)
FutureBuilder<List>(
future: candidateInfo(i, widget.ethClient,widget.electionaddress),
builder: (context, candidatesnapshot) {
if (candidatesnapshot.connectionState ==
ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
return Card( //card to represent the candidate
color: Colors.cyan,
child: SizedBox(height: 100,
child: Center(
child: ListTile(
title: Text('Name: ${candidatesnapshot.data![0][0]}'),
subtitle: Text('Votes: ${candidatesnapshot.data![0][1]}'),
leading: ConstrainedBox(
constraints: const BoxConstraints(
minHeight: 90,
minWidth: 90,
maxHeight: 100,
maxWidth: 100,
),
child:const Image(image: AssetImage('assets/undraw/electionday.png')),
),
trailing: ElevatedButton(
onPressed: ()async {
try{
await vote(i,widget.ethClient,privatekeyController.text,widget.electionaddress);
await registerAuth();
gotoDashboard();
showSnackBar(succesdetailsnackSnack);
}catch(e){
if (kDebugMode) {
print(e);
}
showSnackBar(errordetailsnackSnack);
gotoDashboard();
}
}, child: const Text('Vote'),),
),
),
),
);
}
})
],
);
}
},
),
),
],
),
),
),
);
}else{
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.cyan,
leading: IconButton(onPressed: (){signOut();},icon: const Icon(Icons.logout_sharp),),
title:const Text('Vote'),
actions: [
IconButton(onPressed:(){
refresh();
}, icon: const Icon(Icons.refresh))
],
),
body: const Center(child: Text('you are not authorized please authorize first'),),
);
}
}
//snackbar
SnackBar errordetailsnackSnack = const SnackBar(content: Text(' already voted or please check your internet connection'));
SnackBar succesdetailsnackSnack = const SnackBar(content: Text('successfull'));
SnackBar voterSnack = const SnackBar(content: Text('you are a voter logout from voter account'));
SnackBar adminSnack = const SnackBar(content: Text('you are an admin logout from Admin account'));
// SnackBar errorSnack = const SnackBar(content: Text('Fill all the details'));
// SnackBar datanullSnack = const SnackBar(content: Text('No users registerd yet'));
//function to show snackbar
ScaffoldFeatureController<SnackBar, SnackBarClosedReason> showSnackBar(SnackBar snackBar) {
return ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
void refresh() {
setState(() {});
}
Future<void> registerAuth() async {
var voterdetails = widget.votermap;
try {
await FirebaseFirestore.instance.collection('Election').doc(widget.electionName).collection('voterAuth').doc(voterdetails['adharnum']).update({'isVoted':true});
print('updated data aaaaaaaaaaaaaaa');
} catch (e) {
if (kDebugMode) {
print('failed to register on firebase $e');
}
}
}
void gotoDashboard(){
Navigator.pushAndRemoveUntil(context,MaterialPageRoute(builder:(context)=>VoterHome(ethClient: widget.ethClient,
electionName: widget.electionName, electionaddress: widget.electionaddress)), (route) => false);
}
}
One way to achieve what you want is by making your page retain its state.
Try this code
You have to add with AutomaticKeepAliveClientMixin to the screen like in the snippet below.
Override this #override bool get wantKeepAlive => true;.
Inside build method, add this super.build(context);.
class _TestScreen extends State<TestScreen> with AutomaticKeepAliveClientMixin<TestScreen> {
#override
bool get wantKeepAlive => true;
Widget build(BuildContext context) {
super.build(context);
return Scaffold();
}
}
After doing this, your page will not call initState() everytime that page is loaded.
When you navigate from VoteHome page to VoteRegister page, you use the push method. The push method returns a Future object. You can use the then method of Future to execute your code after VoteRegister was popped from the navigation stack or in other words the user pressed back button in appbar.
Navigator.of(context)
.push(MaterialPageRoute(
builder: (context) => VoteRegister(electionName:widget.electionName,ethClient: widget.ethClient, electionaddress:widget.electionaddress,adhar:adhar,)))
.then((value) {
// you can do what you need here
// setState etc.
// also reload your data here
});
Why does text form field re-render when user clicks on it in Flutter?
My Flutter form contains a TextFormField for Name. When my user clicks on it, the entire form immediately re-renders (reloads), making it impossible for my user to enter anything.
Code
The TextFormField is commented so that you can easily find it.
You'll notice that this page also contains a second field that works perfectly. It's a Switch inside a StatefulBuilder that handles setting a TextEditingController for _importantController.
<!-- language: flutter -->
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/material.dart';
class CrudPage2 extends StatefulWidget {
final String docId;
const CrudPage2({Key? key, required this.docId}) : super(key: key);
#override
CrudPage2State createState() => CrudPage2State();
}
class CrudPage2State extends State<CrudPage2> {
late String name = "";
late bool isImportant = false;
final TextEditingController _nameController = TextEditingController();
final TextEditingController _importantController = TextEditingController();
Stream<DocumentSnapshot<Object?>> groceryItem(docID) =>
FirebaseFirestore.instance
.collection("groceries")
.doc(docID)
.snapshots();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(),
),
title: Text("Grocery Item"),
),
body: SizedBox(
width: double.infinity,
child: Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom + 20),
child: StreamBuilder<DocumentSnapshot>(
stream: groceryItem(widget.docId),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> streamSnapshot) {
if (streamSnapshot.connectionState == ConnectionState.waiting) {
print("****** Loading ******"); // debugging
return const Text("Loading");
} else if (streamSnapshot.hasData) {
if (widget.docId != "NEW") {
// Retrieve existing item
var jsonData = streamSnapshot.data?.data();
Map<String, dynamic> myData = jsonData as Map<String, dynamic>;
name = myData['name'];
isImportant = myData['important'];
}
_nameController.text = name;
if (isImportant) {
_importantController.text = "true";
} else {
_importantController.text = "false";
}
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//--------------------------------------------------------
// PROBLEM: Clicking on this field re-renders entire form.
Flexible(
child: TextFormField(
controller: _nameController,
decoration: const InputDecoration(labelText: 'Name'),
),
),
//--------------------------------------------------------
// No problem with this switch
StatefulBuilder(
builder: (BuildContext context, StateSetter importantStateSetter) {
return Row(
children: [
const Text("Important: "),
Switch(
value: isImportant,
onChanged: (value) {
importantStateSetter(() => isImportant = value);
},
),
],
);
},
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
child: ElevatedButton(
child: const Text('Cancel'),
onPressed: () async {
Navigator.of(context).pop();
}),
),
const SizedBox(
width: 10,
),
SizedBox(
child: ElevatedButton(
child: const Text("Submit"),
onPressed: () async {
final String name = _nameController.text;
if (widget.docId == 'NEW') {
addGroceryItem(name, 1.0, "test",
isImportant);
} else {
updateGroceryItem(widget.docId, name,
1.0, "test", isImportant);
}
// Clear the text fields
_nameController.text = '';
_importantController.text = "";
// Hide the bottom sheet
Navigator.of(context).pop();
},
),
)
],
),
],
);
} else {
return const Text("No Data");
}
})
),
),
);
} // Widget Build
//-------------------------------------------------------------
// Add New Grocery Item
//-------------------------------------------------------------
Future<void> addGroceryItem(
String name, double quantity, String category, bool isImportant) async {
await FirebaseFirestore.instance.collection('groceries').add({
"active": true,
"name": name,
"quantity": quantity,
"category": category,
"important": isImportant
});
}
//-------------------------------------------------------------
// Update Existing Grocery Item
//-------------------------------------------------------------
Future<void> updateGroceryItem(String docID, String name, double quantity,
String category, bool isImportant) async {
await FirebaseFirestore.instance.collection('groceries').doc(docID).update({
"active": true,
"name": name,
"quantity": quantity,
"category": category,
"important": isImportant
});
}
}
I added print("****** Loading ******"); line to help debug. When user clicks on text form field, the Console displays:
I/flutter (28767): ****** Loading ******
I/flutter (28767): ****** Loading ******
Why is the stream refreshing every time this widget is clicked?
Thank you for your time!
After a lot of Googling, I decided that my problem was coming from doing this entirely wrong. Here are some of the changes I made:
Pass-in values as JSON object parameter
Eliminate call to Firebase
Eliminate Stream Builder
Code below solves my problem using these changes:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class CrudPage2 extends StatefulWidget {
final String docId;
final Object? docSnap;
const CrudPage2({Key? key,
required this.docId,
required this.docSnap})
: super(key: key);
#override
CrudPage2State createState() => CrudPage2State();
}
class CrudPage2State extends State<CrudPage2> {
//--- Form State Variables...
late String name = "";
late bool isImportant = false;
//--- Controllers for Form Fields...
final TextEditingController _nameController = TextEditingController();
final TextEditingController _importantController = TextEditingController();
#override
initState() {
super.initState();
if (widget.docId != "NEW") {
Map<String, dynamic> myData = widget.docSnap as Map<String, dynamic>;
name = myData['name'];
isImportant = myData['important'];
}
_nameController.text = name;
if (isImportant) {
_importantController.text = "true";
} else {
_importantController.text = "false";
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(),
),
title: Text("Grocery Item"),
),
body: SizedBox(
width: double.infinity,
child: Padding(
padding: EdgeInsets.only(
top: 20,
left: 20,
right: 20,
bottom: MediaQuery.of(context).viewInsets.bottom + 20),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
controller: _nameController,
decoration: const InputDecoration(labelText: 'Name'),
),
StatefulBuilder(
builder:
(BuildContext context, StateSetter importantStateSetter) {
return Row(
children: [
const Text("Important: "),
Switch(
value: isImportant,
onChanged: (value) {
importantStateSetter(() => isImportant = value);
},
),
],
);
},
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 110,
child: ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(
Colors.grey),
padding: MaterialStateProperty.all(
const EdgeInsets.all(5)),
textStyle: MaterialStateProperty.all(
const TextStyle(fontSize: 24))),
child: const Text('Cancel'),
onPressed: () async {
Navigator.of(context).pop();
}),
),
SizedBox(
width: 200,
child: ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.green),
padding: MaterialStateProperty.all(
const EdgeInsets.all(5)),
textStyle: MaterialStateProperty.all(
const TextStyle(fontSize: 24))),
child: const Text("Submit"),
onPressed: () async {
final String name = _nameController.text;
if (widget.docId == 'NEW') {
addGroceryItem(name, 1.0, "Test",
isImportant);
} else {
updateGroceryItem(widget.docId, name,
1.0, "Test", isImportant);
}
// Clear the text fields
_nameController.text = '';
_importantController.text = "";
// Hide the bottom sheet
Navigator.of(context).pop();
},
),
)
],
),
]
)
)
),
);
} // Widget Build
Future<void> addGroceryItem(
String name, double quantity, String category, bool isImportant) async {
await FirebaseFirestore.instance.collection('groceries').add({
"active": true,
"name": name,
"quantity": quantity,
"category": category,
"important": isImportant
});
}
Future<void> updateGroceryItem(String docID, String name, double quantity,
String category, bool isImportant) async {
await FirebaseFirestore.instance.collection('groceries').doc(docID).update({
"active": true,
"name": name,
"quantity": quantity,
"category": category,
"important": isImportant
});
}
}
Any comments and/or suggestions are still appreciated.
I hope this helps someone else in the future.
I have a screen which shows list of customers using listview. Next when I click on a customer I want to show the notes(records) only of that particular customer(customerId) in next screen in listview. I know how to display all the records of table. but how to display only certain records?? Neither there is any error nor the listview is being displayed. I dont know where am I going wrong.
List<CustomerNote> cnoteList;
int count = 0;
if (cnoteList == null) {
cnoteList = List<CustomerNote>();
updateCustomerNotes();
}
db_service.dart
Future<List<CustomerNote>> getCustomerNotes(int customer) async {
await DB.init();
var res = await DB.rawQuery("noteDetails WHERE custId = '$customer'");
int count = res.length;
List<CustomerNote> cnotelist = List<CustomerNote>();
for (int i = 0; i < count; i++) {
cnotelist.add(CustomerNote.fromMap(res[i]));
}
return cnotelist;
}
People_List.dart //this is the file which displays list of customers
import 'package:customer/models/Note.dart';
import 'package:customer/models/addCustomer.dart';
import 'package:customer/screens/New_Note.dart';
import 'package:customer/screens/Note_info.dart';
import 'package:customer/screens/User_Settings.dart';
import 'package:customer/screens/add_person.dart';
import 'package:customer/services/db_service.dart';
import 'package:customer/utils/database_helper.dart';
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:sqflite/sqflite.dart';
class People_List extends StatefulWidget{
#override
State<StatefulWidget> createState() {
return People_ListState();
}
}
class People_ListState extends State<People_List> with SingleTickerProviderStateMixin{
DBService dbService = DBService();
List<AddCustomer> customerList;
int count = 0;
static final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();
var _isSelectedItemIndex;
TextEditingController _searchQuery;
bool _isSearching = false;
String searchQuery = "Search query";
#override
void initState() {
super.initState();
_searchQuery = new TextEditingController();
}
void _startSearch() {
print("open search box");
ModalRoute
.of(context)
.addLocalHistoryEntry(new LocalHistoryEntry(onRemove: _stopSearching));
setState(() {
_isSearching = true;
});
}
void _stopSearching() {
_clearSearchQuery();
setState(() {
_isSearching = false;
});
}
void _clearSearchQuery() {
print("close search box");
setState(() {
_searchQuery.clear();
updateSearchQuery("Search query");
});
}
Widget _buildTitle(BuildContext context) {
var horizontalTitleAlignment =
Platform.isIOS ? CrossAxisAlignment.center : CrossAxisAlignment.start;
return new InkWell(
onTap: () => scaffoldKey.currentState.openDrawer(),
child: new Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: horizontalTitleAlignment,
children: <Widget>[
const Text(''),
],
),
),
);
}
Widget _buildSearchField() {
return new TextField(
controller: _searchQuery,
autofocus: true,
decoration: const InputDecoration(
hintText: 'Search...',
border: InputBorder.none,
hintStyle: const TextStyle(color: Colors.white30),
),
style: const TextStyle(color: Colors.white, fontSize: 16.0),
onChanged: updateSearchQuery,
);
}
void updateSearchQuery(String newQuery) {
setState(() {
searchQuery = newQuery;
});
print("search query " + newQuery);
}
List<Widget> _buildActions() {
if (_isSearching) {
return <Widget>[
new IconButton(
icon: const Icon(Icons.clear),
onPressed: () {
if (_searchQuery == null || _searchQuery.text.isEmpty) {
Navigator.pop(context);
return;
}
_clearSearchQuery();
},
),
];
}
return <Widget>[
new IconButton(
icon: const Icon(Icons.search),
onPressed: _startSearch,
),
];
}
#override
Widget build(BuildContext context) {
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
if (customerList == null) {
customerList = List<AddCustomer>();
updateListView();
}
return Scaffold(
appBar: new AppBar(
leading: _isSearching ? const BackButton() : null,
title: _isSearching ? _buildSearchField() : _buildTitle(context),
actions: _buildActions(),
),
body:getCustomerListView(),
floatingActionButton: FloatingActionButton(
onPressed: () {
navigateToCustomer(AddCustomer(), 'Add Person');
},
child: const Icon(Icons.add),
),
bottomNavigationBar:Row (
children: <Widget>[
buildNavBarItem(Icons.home,0,"Home"),
buildNavBarItem(Icons.fiber_new_rounded,1,"Upcoming"),
buildNavBarItem(Icons.history,2,"History"),
buildNavBarItem(Icons.account_circle,3,"Account"),
],
),
);
}
ListView getCustomerListView() {
TextStyle titleStyle = Theme.of(context).textTheme.subhead;
return ListView.builder(
itemCount: count,
itemBuilder: (BuildContext context, int position) {
return Card(
color: Colors.white,
elevation: 2.0,
child: ListTile(
/*trailing: CircleAvatar(
backgroundColor: getPriorityColor(this.noteList[position].priority),
child: getPriorityIcon(this.noteList[position].priority),
),*/
title: Text(this.customerList[position].custName, style: titleStyle,),
//subtitle: Text(this.customerList[position].date),
onTap: () {
},
),
);
},
);
}
void navigateToCustomer(AddCustomer customer, String title) async {
bool result = await Navigator.push(context, MaterialPageRoute(builder: (context) {
return AddPerson(customer, title);
}));
if (result == true) {
updateListView();
}
}
void updateListView() {
final Future<Database> dbFuture = DB.init();
dbFuture.then((database) {
Future<List<AddCustomer>> customerListFuture = dbService.getCustomerList();
customerListFuture.then((customerList) {
setState(() {
this.customerList = customerList;
this.count = customerList.length;
});
});
});
}
Widget buildNavBarItem(IconData icon,int index,title) {
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
return GestureDetector(
onTap: () {
setState(() {
_isSelectedItemIndex=index;
if(_isSelectedItemIndex==3) {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => User_Settings()));
}
});
},
child: Container(
height: height * 0.09,
width: width / 4,
decoration: index==_isSelectedItemIndex?BoxDecoration(
border: Border(
bottom: BorderSide(width: 4,color: Theme.of(context).primaryColor),
),
gradient: LinearGradient(colors: [
Theme.of(context).primaryColor.withOpacity(0.3),
Theme.of(context).primaryColor.withOpacity(0.015),
],begin: Alignment.bottomCenter,end: Alignment.topCenter)
):BoxDecoration(),
child: Column(
children: <Widget>[
InkWell(
child: Icon(icon,
color: index==_isSelectedItemIndex? Theme.of(context).primaryColor:Colors.black54,
),
),
Text(title)
],)),
);
}
}
Note_Info.dart
class Note_Info extends StatefulWidget{
final String appBarTitle;
final AddCustomer customer;
Note_Info(this. customer, this.appBarTitle);
#override
State<StatefulWidget> createState() {
return Note_InfoState(this.customer,this.appBarTitle);
}
}
class Note_InfoState extends State<Note_Info> {
CustomerNote note=CustomerNote();
DBService dbService = DBService();
List<CustomerNote> cnoteList;
int count = 0;
String appBarTitle;
AddCustomer customer;
Note_InfoState(this.customer, this.appBarTitle);
PickedFile _imageFile;
final ImagePicker _picker = ImagePicker();
bool rememberMe = false;
DateTime _date = DateTime.now();
TextEditingController custNameController = TextEditingController();
void getImage(ImageSource source) async {
final pickedFile = await _picker.getImage(
source: source);
setState(() {
_imageFile = pickedFile;
});
}
#override
Widget build(BuildContext context) {
if (noteList == null) {
noteList = List<CustomerNote>();
updateCustomerNotes();
}
var height = MediaQuery.of(context).size.height;
custNameController.text = customer.custName;
return DefaultTabController(
length: 4,
child: Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(
Icons.add,
),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => NewNote()));
},
)
],
),
body: Container(
child: Column(
children: <Widget>[
TextField(controller: custNameController,
style: TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
textAlign: TextAlign.center),
Padding(
padding: const EdgeInsets.all(15.0),
child: Row(children: [
ImageProfile(),
Padding(
padding: const EdgeInsets.only(left: 30.0),
child: IconButton(
icon: Icon(
Icons.call,
color: Colors.green,
size: 45,
),
onPressed: () {
},
),
),
],),
),
SizedBox(
height: 50,
child: AppBar(
bottom: TabBar(
tabs: [
Tab(
text: "All",
),
Tab(
text: "Pending",
),
Tab(
text: "Cancelled",
),
Tab(
text: "Completed",
),
],
),
),
),
// create widgets for each tab bar here
Expanded(
child: TabBarView(
children: [
// first tab bar view widget
Container(
child: getNoteListView(),
),
// second tab bar view widget
Container(
child: Center(
child: Text(
'Pending Items',
),
),
),
Container(
child: Center(
child: Text(
'Cancelled',
),
),
),
Container(
child: Center(
child: Text(
'Completed',
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 55.0,
width: 200,
child: RaisedButton(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
color: Theme
.of(context)
.primaryColorDark,
textColor: Colors.white,
child: Text('Save', textScaleFactor: 1.5,),
onPressed: () {
setState(() {
//_reset();
});
},
),
),
),
]
),
)
));
}
void updateCustomerNotes() {
final Future<Database> dbFuture = DB.init();
dbFuture.then((database) {
int customerId=customer.custId;
Future<List<CustomerNote>> noteListFuture = dbService.getCustomerNotes(customerId);
noteListFuture.then((cnoteList) {
setState(() {
this.cnoteList = cnoteList;
//this.count = cnoteList.length;
});
});
});
}
ListView getNoteListView() {
TextStyle titleStyle = Theme.of(context).textTheme.subhead;
return ListView.builder(
itemCount: count,
itemBuilder: (BuildContext context, int position) {
return Card(
color: Colors.white,
elevation: 2.0,
child: ListTile(
title: Text(this.cnoteList[position].note, style: titleStyle,),
subtitle: Text(this.cnoteList[position].date),
trailing: GestureDetector(
child: Icon(Icons.delete, color: Colors.grey,),
onTap: () {
},
),
onTap: () {
},
),
);
},
);
}
void _showSnackBar(BuildContext context, String message) {
final snackBar = SnackBar(content: Text(message));
Scaffold.of(context).showSnackBar(snackBar);
}
Widget ImageProfile() {
return Center(
child: CircleAvatar(
radius: 80.0,
backgroundImage: AssetImage('images/person_icon.jpg')
),
);
}
}
If u want to get some specific data from the server then you need to provide (where: ) in your query such as
List<Map> result = await db.query(
DatabaseHelper.table,
columns: columnsToSelect,
where: whereString,
whereArgs: whereArguments);
// print the results
result.forEach((row) => print(row));
// {_id: 1, name: Bob, age: 23}
}
Note your query can be different from the above one.
and if you want to get the same specific data from already fetched data then also you need to use the where clause such as
final outData = responseData.where((i) => i.userId == customerId).toList();
and then pass the outData to next page through params.
I'm currently developing a Fingerspelling learning app. In the fingerspelling_screen.dart file, user will be able to choose which category that he/she would like to learn first. When the user chooses either one of the button, the app will query Firebase Firestore to get a list of signs object which contains the name of the sign, the category to which the sign belongs to and the video URL of each sign before navigating user to sign_video.dart which is a video player. From there, user can press next to switch to the next sign in the category. When the user presses on the check sign button, the user will be navigating to the check sign_checker.dart to check if they are performing a sign correctly.
I've been passing the 'category' variable from one screen to another using constructor and I do not think it is very effective. Is there any way I could solve this?
I wish to initilize vidlist variable (a variable that stores a list of Sign objects) in the initState because the video player controller needs to be initialized first. I've tried using StreamProvider, but for some reason, I couldn't initialize the vidlist variable in initState. The vidlist variable would always be null.
Thank you.
fingerspelling.dart
import 'package:slem_proto/screens/sign_video.dart';
import 'package:slem_proto/shared/constants.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:undraw/undraw.dart';
class FingerspellingScreen extends StatelessWidget {
static String routeName = 'fingerspelling_screen';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.only(left: 20, right: 20, top: 50),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Fingerspelling',
style: kHeadingTextStyle,
),
SizedBox(height: 30),
FingerspellingTab(
title: 'Alphabets',
illustration: UnDrawIllustration.learning,
onTap: () {
print('Alphabet tab tapped');
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SignVideoScreen(
category: 'alphabets',
),
),
);
},
),
SizedBox(
height: 15,
),
FingerspellingTab(
title: 'Numbers',
illustration: UnDrawIllustration.calculator,
onTap: () {
print('Number tab tapped');
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SignVideoScreen(
category: 'numbers',
),
),
);
},
),
],
),
),
);
}
}
class FingerspellingTab extends StatelessWidget {
final String title;
final UnDrawIllustration illustration;
final Function onTap;
const FingerspellingTab(
{#required this.title,
#required this.illustration,
#required this.onTap});
#override
Widget build(BuildContext context) {
return InkWell(
child: Container(
width: double.infinity,
height: 250,
decoration: BoxDecoration(
color: Color.fromRGBO(58, 139, 238, 0.2),
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: const EdgeInsets.only(left: 20, top: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: kHeadingTextStyle.copyWith(
color: Color.fromRGBO(80, 80, 80, 0.8),
fontSize: 25,
),
),
SizedBox(
height: 15,
),
Container(
height: 150,
child: UnDraw(
color: Color(0xFF6C63FF),
illustration: illustration,
placeholder: Text(
"Illustration is loading..."), //optional, default is the CircularProgressIndicator().
),
),
],
),
),
),
onTap: onTap,
);
}
}
database.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:slem_proto/models/sign.dart';
class DatabaseService {
// collection reference
final CollectionReference signCollection =
FirebaseFirestore.instance.collection('signs');
// Sign list from snapshot
List<Sign> _signListFromSnapshot(QuerySnapshot snapshot) {
return snapshot.docs.map((doc) {
return Sign(
category: doc.data()['category'] ?? '',
sign_name: doc.data()['sign_name'] ?? '',
sign_url: doc.data()['sign_url'] ?? '',
);
}).toList();
}
// get signs stream
Stream<List<Sign>> get signs {
return signCollection.snapshots().map(_signListFromSnapshot);
}
// get signs stream
Stream<List<Sign>> getSignFromCategory({String category}) {
return signCollection
.where('category', isEqualTo: category)
.snapshots()
.map(_signListFromSnapshot);
}
}
sign_checker.dart
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
class SignChecker extends StatefulWidget {
final String category;
SignChecker({this.category});
#override
_SignCheckerState createState() => _SignCheckerState(category: this.category);
}
class _SignCheckerState extends State<SignChecker> {
final String category;
_SignCheckerState({this.category});
File _image;
bool predictionStarted = false;
bool predictionComplete = false;
var predictionResult = 'Please wait...';
Future getImage() async {
setState(() {
predictionStarted = false;
predictionComplete = false;
});
// Get image from camera
// var image = await ImagePicker.pickImage(source: ImageSource.camera);
// Get image from gallery
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = image;
predictionStarted = true;
});
// Base64 Encode the image
List<int> imageBytes = image.readAsBytesSync();
String base64Image = base64.encode(imageBytes);
// Print the base64 encoded string in console
print(base64Image);
// Send the encoded image with POST request
Map<String, String> headers = {"Accept": "application/json"};
Map body = {"image": base64Image};
// var response = await http.post('http://XX.XXX.XXX.X/automl.php',
// body: body, headers: headers);
var response = await http.post('http://XX.XXX.XXX.X/automl_alphabet.php',
body: body, headers: headers);
// Print the status code returned by server
print('Status code');
print(response.statusCode);
// Get prediction Result
setState(() {
predictionResult = response.body;
predictionComplete = true;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Sign Checker'),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
SizedBox(
height: 20,
),
Text(
'Push the camera button',
textAlign: TextAlign.center,
),
RaisedButton(
onPressed: getImage,
child: Text('Camera'),
),
(_image != null)
? Image.file(
_image,
scale: 50,
)
: Text('No Image Picked'),
predictionBody()
],
),
),
);
}
Widget predictionBody() {
var predictionText = (predictionComplete) ? 'Result' : 'Prediction started';
if (predictionStarted) {
return Column(
children: <Widget>[
Divider(),
Text(predictionText),
Text(predictionResult)
],
);
} else {
return Container();
}
}
}
sign.dart
class Sign {
final String category;
final String sign_name;
final String sign_url;
Sign({this.category, this.sign_name, this.sign_url});
}
Firstly, using constructors to pass variables may not be inefficient, since Flutter only pass on references. Say,
var a = List(...huge list...);
var b = a;
Then the second line is not costly.
Secondly, if you ask about state management, you may try Mobx, Bloc, Redux, etc. There are many ways to do so.
final String url = 'https://onobang.com/flutter';
// here is my backend code decrlareData.dart
class UserDetails {
final String id;
final String firstName, proVinsi, link, profileUrl, ket, kab;
UserDetails({
this.id,
this.firstName,
this.proVinsi,
this.link,
this.profileUrl,
this.ket,
this.kab,
});
factory UserDetails.fromJson(Map<String, dynamic> json) {
return new UserDetails(
id: json['id'],
firstName: json['name'],
proVinsi: json['provinsi'],
profileUrl:
"https://onobang.com/daiku/ajaximageupload/manajemen/uploads/" +
json['file_name'],
ket: json['ket'],
link: json['link'],
kab: json['kabupaten'],
);
}
}
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:url_launcher/url_launcher.dart';
import 'declareData.dart';
import 'detail.dart';
// here is my fetch data and view with search result,
class HomePage extends StatefulWidget {
HomePage({Key key}) : super(key: key);
#override
_HomePageState createState() => new _HomePageState();
}
class _HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
List<UserDetails> _searchResult = [];
List<UserDetails> _userDetails = [];
TextEditingController controller = new TextEditingController();
// Get json result and convert it to model. Then add
Future<Null> getUserDetails() async {
final response = await http.get(url);
final responseJson = json.decode(response.body);
setState(() {
for (Map user in responseJson) {
_userDetails.add(UserDetails.fromJson(user));
}
});
}
#override
void initState() {
super.initState();
getUserDetails();
}
Widget _buildUsersList() {
return new ListView.builder(
itemCount: _userDetails.length,
itemBuilder: (context, index) {
return new Card(
child: new ListTile(
leading: new CircleAvatar(
backgroundImage: new NetworkImage(
_userDetails[index].profileUrl,
),
),
title: new Text(' Nama : ' +
_userDetails[index].firstName +
' ' +
_userDetails[index].kab),
subtitle: new Text('Provinsi : ' + _userDetails[index].proVinsi ),
isThreeLine: true,
trailing: (IconButton(
icon: Icon(Icons.expand_more),
)
),
onTap: () {
var route = new MaterialPageRoute(
builder: (BuildContext context) =>
new SecondScreen(value: _userDetails[index]),
);
Navigator.of(context).push(route);
},
),
margin: const EdgeInsets.all(0.0),
);
},
);
}
//Widget futureBuilder() {
//future:
Widget _buildSearchResults() {
return new ListView.builder(
itemCount: _searchResult.length,
itemBuilder: (context, i) {
return new Card(
child: new ListTile(
leading: new CircleAvatar(
backgroundImage: new NetworkImage(
_searchResult[i].profileUrl,
),
),
title: new Text(_searchResult[i].firstName +
' || Kab ' +
_searchResult[i].kab),
subtitle: new Text('Prov : ' + _searchResult[i].proVinsi),
onTap: () {
var route = new MaterialPageRoute(
builder: (BuildContext context) =>
new SecondScreen(value: _searchResult[i]),
);
Navigator.of(context).push(route);
},
),
margin: const EdgeInsets.all(0.0),
);
},
);
}
Widget _buildSearchBox() {
return new Padding(
padding: const EdgeInsets.all(8.0),
child: new Card(
child: new ListTile(
leading: new Icon(Icons.search),
title: new TextField(
controller: controller,
decoration: new InputDecoration(
hintText: 'Search', border: InputBorder.none),
onChanged: onSearchTextChanged,
),
trailing: new IconButton(
icon: new Icon(Icons.cancel),
onPressed: () {
controller.clear();
onSearchTextChanged('');
},
),
),
),
);
}
Widget _buildBody() {
return new Column(
children: <Widget>[
FlatButton.icon(
color: Colors.white,
icon: Icon(FontAwesomeIcons.whatsapp), //`Icon` to display
label: Text('089xxxx465'), //`Text` to display
onPressed: () {
launch('https://www.instagram.com/?hl=id');
},
),
new Container(
color: Theme.of(context).primaryColor, child: _buildSearchBox()),
new Expanded(
child: _searchResult.length != 0 || controller.text.isNotEmpty
? _buildSearchResults()
: _buildUsersList()),
],
);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: _buildBody(),
// body: new RefreshIndicator(child: null, onRefresh: null),
resizeToAvoidBottomPadding: true,
);
}
onSearchTextChanged(String text) async {
_searchResult.clear();
if (text.isEmpty) {
setState(() {});
return;
}
_userDetails.forEach((userDetail) {
if (userDetail.firstName.toUpperCase().contains(text.toUpperCase()) ||
userDetail.proVinsi.toUpperCase().contains(text.toUpperCase())||
userDetail.kab.toUpperCase().contains(text.toUpperCase()))
_searchResult.add(userDetail);
});
setState(() {});
}
}
import 'package:flutter/material.dart';
import 'declareData.dart';
import 'package:flutube/flutube.dart';
import 'package:flutter/services.dart';
// here is the single post
class SecondScreen extends StatefulWidget {
final UserDetails value;
SecondScreen({Key key, this.value}) : super(key: key);
#override
_SecondScreenState createState() => _SecondScreenState();
}
//detail start
class _SecondScreenState extends State<SecondScreen> {
int currentPos;
String stateText;
#override
void initState() {
currentPos = 0;
stateText = "Video not started";
super.initState();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('Profil Ustad')),
body: new Container(
child: new Center(
child: Column(
children: <Widget>[
Padding(
child: new Text(
'${widget.value.firstName}',
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0,
),
textAlign: TextAlign.center,
),
padding: EdgeInsets.only(top: 20.0),
),
/* Padding(
//`widget` is the current configuration. A State object's configuration
//is the corresponding StatefulWidget instance.
child: Image.network('${widget.value.profileUrl}'),
padding: EdgeInsets.all(12.0),
),*/
Padding(
child: new Text(
'Nama : ${widget.value.firstName}',
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
),
padding: EdgeInsets.all(10.0),
),
Padding(
child: new Text(
'PROVINSI : ${widget.value.proVinsi}',
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
),
padding: EdgeInsets.all(0.0),
),
Padding(
child: new Text(
'Ket : ${widget.value.ket}',
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.justify,
),
padding: EdgeInsets.all(10.0),
),
],
),
),
),
);
}
}
i'm trying to make a specific search in flutter, the case is, i'd like user can choose option that was, province and district , than after user select the specific location they want, user click a button than we fetch data from mysql json.so i wish i can change value in url variable than i can get specific data from my json.
final String url = 'https://onobang.com/flutter/index.php?'+'province='
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
title: "Para Dai",
home: new DropDown(),
));
}
import 'package:flutter/material.dart';
class DropDown extends StatefulWidget {
DropDown() : super();
final String title = "DropDown Demo";
#override
DropDownState createState() => DropDownState();
}
class Provinces {
int id;
String name;
Provinces(this.id, this.name);
static List<Provinces> getCompanies() {
return <Provinces>[
Provinces(1, 'Central Java'),
Provinces(2, 'East kalimantan'),
Provinces(3, 'East java'),
Provinces(4, 'Bali'),
Provinces(5, 'Borneo'),
];
}
}
class DropDownState extends State<DropDown> {
//
List<Provinces> _provinceses = Provinces.getCompanies();
List<DropdownMenuItem<Provinces>> _dropdownMenuItems;
Provinces _selectedProvinces;
#override
void initState() {
_dropdownMenuItems = buildDropdownMenuItems(_provinceses);
_selectedProvinces = _dropdownMenuItems[0].value;
super.initState();
}
// here the url i wish can dynamicly edit by user input
final String url = 'https://onobang.com/flutter/index.php?'+'province='_selectedProvinsi.name+'district'some.district;
List<DropdownMenuItem<Provinces>> buildDropdownMenuItems(List provinceses) {
List<DropdownMenuItem<Provinces>> items = List();
for (Provinces province in provinceses) {
items.add(
DropdownMenuItem(
value: province,
child: Text(province.name),
),
);
}
return items;
}
onChangeDropdownItem(Provinces selectedProvinces) {
setState(() {
_selectedProvinces = selectedProvinces;
});
}
#override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
home: new Scaffold(
appBar: new AppBar(
title: new Text("DropDown Button Example"),
),
body: new Container(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Select a province"),
SizedBox(
height: 20.0,
),
DropdownButton(
value: _selectedProvinces,
items: _dropdownMenuItems,
onChanged: onChangeDropdownItem,
),
SizedBox(
height: 20.0,
),
Text('Selected: ${_selectedProvinces.name}'),
],
),
),
),
),
);
}
}
Demo
Do you need something like this?
You can build it locally using this repo Github.
What to Do
Make District class that similiar to Province
Initiate Dropdown for District
Set initial value for selectedDistrict
Lastly, modify URL before calling setState
Full Code
import 'package:flutter/material.dart';
class DropDown extends StatefulWidget {
DropDown() : super();
final String title = "DropDown Demo";
#override
DropDownState createState() => DropDownState();
}
class Province {
int id;
String name;
Province(this.id, this.name);
static List<Province> getProvinceList() {
return <Province>[
Province(1, 'Central Java'),
Province(2, 'East kalimantan'),
Province(3, 'East java'),
Province(4, 'Bali'),
Province(5, 'Borneo'),
];
}
}
// ADD THIS
class District {
int id;
String name;
District(this.id, this.name);
static List<District> getDistrictList() {
return <District>[
District(1, 'Demak'),
District(2, 'Solo'),
District(3, 'Sidoarjo'),
District(4, 'Bandung'),
];
}
}
class DropDownState extends State<DropDown> {
String finalUrl = '';
List<Province> _provinces = Province.getProvinceList();
List<DropdownMenuItem<Province>> _dropdownMenuItems;
Province _selectedProvince;
// ADD THIS
List<District> _disctricts = District.getDistrictList();
List<DropdownMenuItem<District>> _dropdownMenuDistricts;
District _selectedDistrict;
#override
void initState() {
_dropdownMenuItems = buildDropdownMenuItems(_provinces);
_dropdownMenuDistricts = buildDropdownDistricts(_disctricts); // Add this
_selectedProvince = _dropdownMenuItems[0].value;
_selectedDistrict = _dropdownMenuDistricts[0].value; // Add this
super.initState();
}
List<DropdownMenuItem<Province>> buildDropdownMenuItems(List provinceses) {
List<DropdownMenuItem<Province>> items = List();
for (var province in provinceses) {
items.add(
DropdownMenuItem(
value: province,
child: Text(province.name),
),
);
}
return items;
}
// ADD THIS
List<DropdownMenuItem<District>> buildDropdownDistricts(List<District> districts) {
List<DropdownMenuItem<District>> items = List();
for (var district in districts) {
items.add(
DropdownMenuItem(
value: district,
child: Text(district.name),
),
);
}
return items;
}
onChangeDropdownItem(Province newProvince) {
// Add this
final String url = 'https://onobang.com/flutter/index.php?province=${newProvince.name}&district=${_selectedDistrict.name}';
setState(() {
_selectedProvince = newProvince;
finalUrl = url; // Add this
});
}
onChangeDistrict(District newDistrict) {
// Add this
final String url = 'https://onobang.com/flutter/index.php?province=${_selectedProvince.name}&district=${newDistrict.name}';
setState(() {
_selectedDistrict = newDistrict;
finalUrl = url; // Add this
});
}
#override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
home: new Scaffold(
appBar: new AppBar(
title: new Text("DropDown Button Example"),
),
body: new Container(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Select a province"),
SizedBox(
height: 20.0,
),
DropdownButton(
value: _selectedProvince,
items: _dropdownMenuItems,
onChanged: onChangeDropdownItem,
),
SizedBox(
height: 20.0,
),
Text('Selected: ${_selectedProvince.name}'),
SizedBox(
height: 20.0,
),
Text("Select a district"),
SizedBox(
height: 20.0,
),
// Add this
DropdownButton(
value: _selectedDistrict,
items: _dropdownMenuDistricts,
onChanged: onChangeDistrict,
),
SizedBox(
height: 20.0,
),
Text('Selected: ${_selectedDistrict.name}'),
SizedBox(
height: 30.0,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('$finalUrl'),
),
],
),
),
),
),
);
}
}