How to get variable from class to future in flutter? - flutter

I'm trying to update firestore data with update function as below. The variable I want to use in future is inside a class. How can i get variable from outside the future? I want to update data which is i clicked so i need to get id clicked item.the variable I want to use is '??????' I stated with
What can i do for this issue?
class Test extends StatefulWidget {
const Test({Key? key}) : super(key: key);
#override
State<Test> createState() => _TestState();
}
class _TestState extends State<Test> {
final Stream<QuerySnapshot> _usersStream =
FirebaseFirestore.instance.collection('testinfo').snapshots();
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(defaultPadding),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
StreamBuilder<QuerySnapshot>(
stream: _usersStream,
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return const CircularProgressIndicator();
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
}
return SizedBox(
width: double.infinity,
child: DataTable(
columnSpacing: defaultPadding,
columns: const [
DataColumn(
label: Text('Text'),
),
],
rows: _buildList(context, snapshot.data!.docs)));
},
)
]));
}
List<DataRow> _buildList(
BuildContext context, List<DocumentSnapshot> snapshot) {
return snapshot.map((data) => _buildListItem(context, data)).toList();
}
DataRow _buildListItem(BuildContext context, DocumentSnapshot data) {
final ?????? = FirebaseFirestore.instance
.collection('testinfo')
.doc(data.id);
return DataRow(cells: [
DataCell(Text(data['name']!)),
DataCell(Row(children: [
PopupMenuButton<Menu>(
padding: const EdgeInsets.only(right: 2, left: 1, top: 2),
onSelected: (value) async {
if (value == Menu.itemOne) {
controllerName.text = data.get('name');
showDialog(
context: context,
builder: (context) => Dialog(
child: Container(
color: primaryColor,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ListView(
shrinkWrap: true,
children: <Widget>[
TextField(
onChanged: (value) {
candidateName = value;
},
controller: controllerName,
decoration: InputDecoration(
hintText: 'name',)
)
)const ElevatedButton(
onPressed: (updateData),
child: Text('Save'),
),
itemBuilder: (BuildContext context) => <PopupMenuEntry<Menu>>[
const PopupMenuItem<Menu>(value: Menu.itemTwo,
child: Text('edit'),),
Future updateData() async {
await ??????.update({
'name': controllerName.text,
}).then((value) => print('updated.'));
}

UserDetailsModel currentUser;
List<UserDetailsModel> membersDetails = [];
for (int i = 0; i < data.docs.length; i++) {
membersDetails.add(UserDetailsModel.fromJson(
data.docs[i].data()! as Map<String, dynamic>));
}
UserDetailsModel is your model class
you use it later...

Related

Loading page for ListView builder flutter

Hello I would like to have a loading page before all the list is created. To display this list, I get the request info in php and I create cards one by one. The problem is that when the user come on the application, there is a lot of loading round because I put "return CircularProgressIndicator()", I would like that we are on a waiting page until all the cards are not loaded
I tried to set variables and pass them to false until all the cards are loaded but I can't get on this loading page
Here is the code of my page
Future<String> getDataSearch(text, index) async {
if (index != "ff") {
var theUrl =
Uri.parse("https://xf8s7auoez.preview.infomaniak.website/getdata.php");
var res = await http.post(theUrl, body: {
"index": index.toString(),
"post": "index",
"file": "get_data",
});
Map<String, dynamic> data = jsonDecode(res.body);
if (text == 1) {
return data["type"];
} else if (text == 2) {
return data["taille"];
} else if (text == 3) {
return data["prix"];
} else if (text == 5) {
return data["image"];
} else if (text == 6) {
return data["description"];
}
}
var theUrl =
Uri.parse("https://xf8s7auoez.preview.infomaniak.website/getdata.php");
var res = await http.post(theUrl, body: {
"post": "rows",
"file": "get_data",
});
print(res.body);
return res.body;
}
class Type extends StatelessWidget {
Type(this.index);
final int index;
#override
Widget build(context) {
return FutureBuilder<String>(
// future: getUserType(index),
future: getDataSearch(1, index),
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!);
} else {
return SizedBox(width: 10, height: 10, child: Container());
}
});
}
}
class Description extends StatelessWidget {
Description(this.index);
final int index;
#override
Widget build(context) {
return FutureBuilder<String>(
// future: getUserType(index),
future: getDataSearch(6, index),
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!);
} else {
return SizedBox(width: 10, height: 10, child: Container());
}
});
}
}
class Taille extends StatelessWidget {
Taille(this.index);
final int index;
#override
Widget build(context) {
return FutureBuilder<String>(
// future: getUserType(index),
future: getDataSearch(2, index),
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!);
} else {
return SizedBox(width: 10, height: 10, child: Container());
}
});
}
}
class Prix extends StatelessWidget {
Prix(this.index);
final int index;
#override
Widget build(context) {
return FutureBuilder<String>(
//future: getAge(index),
future: getDataSearch(3, index),
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
String bio = snapshot.data.toString();
return Text(bio);
} else {
return SizedBox(width: 10, height: 10, child: Container());
}
});
}
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Mediester',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: RefreshIndicatorView(),
);
}
}
class RefreshIndicatorView extends StatefulWidget {
const RefreshIndicatorView({Key? key}) : super(key: key);
#override
_RefreshIndicatorViewState createState() => _RefreshIndicatorViewState();
}
class _RefreshIndicatorViewState extends State<RefreshIndicatorView> {
int initNumber = 1;
int selectedValue = 1;
final GlobalKey<ScaffoldState> _key = GlobalKey();
#override
initState() {
getDataSearch(4, "ff").then((String result) {
if (initNumber != int.parse(result)) {
setState(() {
initNumber = int.parse(result);
});
}
});
}
#override
Widget build(BuildContext context) {
return RefreshIndicator(
displacement: 250,
backgroundColor: Color.fromARGB(255, 110, 155, 191),
color: Colors.white,
strokeWidth: 3,
triggerMode: RefreshIndicatorTriggerMode.onEdge,
onRefresh: () async {
await Future.delayed(Duration(milliseconds: 1500));
setState(() {
int debug = 0;
});
},
child: Scaffold(
key: _key,
backgroundColor: Color.fromARGB(255, 110, 155, 191),
appBar: BaseAppBar(),
drawer: createDrawer(context),
body: _buildCardDesign(),
),
);
}
Widget _buildCardDesign() {
Future.delayed(const Duration(milliseconds: 1500), () {
if (debugg != 1) {
setState(() {});
debugg = 1;
}
});
return Container(
margin: EdgeInsets.all(5),
child: ListView.builder(
itemCount: initNumber,
shrinkWrap: true,
physics: const BouncingScrollPhysics(
parent: AlwaysScrollableScrollPhysics()),
scrollDirection: Axis.vertical,
prototypeItem: _buildCardView(1),
itemBuilder: (BuildContext context, int index) {
return _buildCardView(index + 1);
}),
);
}
Widget _buildPhoto(index) {
return Container(
child: FutureBuilder<String>(
future: getDataSearch(5, index),
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
return ClipRRect(
borderRadius: BorderRadius.circular(5.0),
child: Image.network(
snapshot.data!,
height: 65.0,
width: 65.0,
fit: BoxFit.cover,
),
);
} else {
return CircularProgressIndicator.adaptive();
}
}));
}
Widget _buildCardView(index) {
return Container(
width: MediaQuery.of(context).size.width,
child: Container(
margin: EdgeInsets.all(10),
height: 100,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(10))),
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ArticlePage(
index, Type(index), Prix(index), Description(index)),
));
},
child: Container(
padding: EdgeInsets.fromLTRB(15, 15, 30, 15),
child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildPhoto(index),
//SizedBox(width: 20,),
DefaultTextStyle(
style: TextStyle(
fontSize: 19,
fontWeight: FontWeight.w800,
color: Color.fromARGB(255, 110, 155, 191)),
child: Container(
padding: EdgeInsets.only(left: 40),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
DefaultTextStyle(
child: Container(child: Type(index)),
style: TextStyle(
color: Color.fromARGB(255, 110, 155, 191),
fontSize: 17)),
DefaultTextStyle(
child: Container(
padding: EdgeInsets.only(top: 8),
child: Taille(index)),
style: TextStyle(
color: Color.fromARGB(255, 168, 168, 168)),
),
Container(
padding: EdgeInsets.only(top: 3),
child: Row(
children: [
Prix(index),
Text(" €"),
],
)),
],
),
),
),
],
),
),
),
),
);
}
}
This can be accomplished using a FutureBuilder. In your RefreshIndicatorView class, the _buildCardDesign widget is currently calling your future, and then building the ListView. Instead, try creating one async function that holds the logic for retrieving the data, and a separate class for the widget that is only responsible for building the widget. Then, you can call the future in the FutureBuilder and show your loading page until it has completed.
In the FutureBuilder, pass your function as the argument to future. Then you can use the variable snapshot to check the status of the future. In your builder function, simply check if(snapshot.hasData), and show the loading page or the listView widget accordingly.
Edit: Here's a simple example that retrieves a List<String> and puts one String in each card. Your new function and widget class would look like this:
List<String> _getStrings() async {
//Async logic here
...
}
Widget MyCard extends StatelessWidget {
final String displayText;
myCard(this.displayText);
#override
Widget build(BuildContext context) {
return Text(displayText);
}
}
And in the home page of your MyApp, you can use something like this for the build method:
FutureBuilder<List<String>>(
future: _getStrings,
builder: (BuildContext context, AsyncSnapshot<List<String>> snapshot) {
if(snapshot.hasData) {
return ListView.builder(
itemBuilder: (BuildContext context, int index) => MyCard(snapshot.data[index])
...
);
} else {
return MyLoadingScreen();
}
});

When i refresh the page i couldn't get firestore realtime data with Flutter

I'm developing flutter web project. When I log in successfully at the first launch of the application, I can get the data in the firestore. However, when I refresh the web page or add new data after the data is received, the updated data does not appear on the screen, it is waiting in an if condition. Is this because Flutter can't draw the refreshed screen? What way can I follow?
**import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:moyes_home_project/view/candidate_addform.dart';
import 'package:moyes_home_project/view/constants.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
import 'candidate_updateform.dart';
enum Menu { itemOne, itemTwo, itemThree }
class CandidatePool extends StatefulWidget {
const CandidatePool({Key? key}) : super(key: key);
#override
State<CandidatePool> createState() => _CandidatePoolState();
}
final Stream<QuerySnapshot> _usersStream =
FirebaseFirestore.instance.collection('candidateinfo').snapshots();
class _CandidatePoolState extends State<CandidatePool> {
#override
Widget build(BuildContext context) {
return SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.all(defaultPadding),
child: Column(
// ignore: prefer_const_literals_to_create_immutables
children: [
const MyFiles(),
const Candidatepooltittle(),
const SizedBox(height: defaultPadding),
],
)));
}
}
class Candidatepooltittle extends StatefulWidget {
const Candidatepooltittle({Key? key}) : super(key: key);
#override
State<Candidatepooltittle> createState() => _CandidatepooltittleState();
}
class _CandidatepooltittleState extends State<Candidatepooltittle> {
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(defaultPadding),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
StreamBuilder<QuerySnapshot>(
stream: _usersStream,
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return const CircularProgressIndicator();
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
}
return SizedBox(
width: double.infinity,
child: DataTable(
columnSpacing: defaultPadding,
columns: const [
DataColumn(
label: Text('test1'),
),
DataColumn(
label: Text('test2'),
),
DataColumn(
label: Text('test3'),
),
DataColumn(
label: Text('test4'),
),
DataColumn(
label: Text('test5'),
),
DataColumn(label: Text(''))
],
rows: snapshot.data!.docs
.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return DataRow(cells: [
DataCell(
Text(data['test5']),
),
DataCell(Text(data['test4']!)),
DataCell(Text(data['test3']!)),
DataCell(Text(data['test2']!)),
const DataCell(Text('test1')),
DataCell(Row(children: [
PopupMenuButton<Menu>(
padding: const EdgeInsets.only(
right: 2, left: 1, top: 2),
onSelected: (value) async {
if (value == Menu.itemOne) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => View(
url: data['fileUrl'],
)));
} else if (value == Menu.itemTwo) {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) =>
Candidateupdateform(document,
candidate: document)));
} else if (value == Menu.itemThree) {
final docdelete = FirebaseFirestore
.instance
.collection('candidateinfo')
.doc(document.id);
docdelete.delete();
}
},
itemBuilder: (BuildContext context) =>
<PopupMenuEntry<Menu>>[
const PopupMenuItem<Menu>(
value: Menu.itemOne,
child: Text('test'),
),
const PopupMenuItem<Menu>(
value: Menu.itemTwo,
child: Text('test'),
),
const PopupMenuItem<Menu>(
value: Menu.itemThree,
child: Text('test'),
)
])
]))
]);
}).toList()));
})
]));
}
}
class View extends StatelessWidget {
PdfViewerController? _pdfViewerController;
final url;
View({Key? key, this.url}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('test'),
),
body: SfPdfViewer.network(
url,
controller: _pdfViewerController,
),
);
}
}
class MyFiles extends StatelessWidget {
const MyFiles({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
final Size _size = MediaQuery.of(context).size;
return Column(children: [
Row(mainAxisAlignment: MainAxisAlignment.end, children: [
ElevatedButton.icon(
style: TextButton.styleFrom(
// ignore: prefer_const_constructors
padding: EdgeInsets.symmetric(
horizontal: defaultPadding * 1.5,
),
),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => Candidateaddform()));
},
icon: const Icon(Icons.add),
label: const Text("test"),
),
])
]);
}
}**

How to Pause and Resume the qr_code_scanner using the NavigationBar

I have a NavigationBar with 3 Destinations and I want to pause or resume the qr_code_scanner depending on what destination is focused, to do this i use a if to evaluate the index and pause or resume the scanner, but i dont now how pass the controller between classes.
My NavigationBar
bottomNavigationBar: NavigationBar(
elevation: 2,
labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected,
selectedIndex: index,
onDestinationSelected: (index) {
setState(() => this.index = index);
if (index == 1) {
widget.controller!.resumeCamera();
} else {
widget.controller!.pauseCamera();
}
},
destinations: const [
NavigationDestination(
icon: Icon(Icons.store_outlined),
selectedIcon: Icon(Icons.store),
label: 'Tienda',
),
NavigationDestination(
icon: Icon(Icons.qr_code_scanner_outlined),
selectedIcon: Icon(Icons.qr_code_scanner),
label: 'Escaner',
),
NavigationDestination(
icon: Icon(Icons.shopping_cart_outlined),
selectedIcon: Icon(Icons.shopping_cart),
label: 'Carrito',
),
],
),
The Home class
class Home extends StatefulWidget {
final QRViewController? controller;
const Home({Key? key, this.controller}) : super(key: key);
#override
State<Home> createState() => _HomeState();
}
My QrScan Class
class QRScanner extends StatefulWidget {
const QRScanner({Key? key}) : super(key: key);
#override
State<StatefulWidget> createState() => QRScannerState();
}
class QRScannerState extends State<QRScanner> {
Barcode? result;
QRViewController? controller;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
#override
void reassemble() {
super.reassemble();
if (Platform.isAndroid) {
controller!.pauseCamera();
}
controller!.resumeCamera();
}
#override
Widget build(BuildContext context) {
void home() {
Home(
controller: controller,
);
}
home();
return Scaffold(
body: Column(
children: <Widget>[
Expanded(child: buildQrView(context)),
Align(
alignment: Alignment.bottomCenter,
child: Container(
alignment: Alignment.center,
height: 100,
color: Colors.black,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.toggleFlash();
setState(() {});
},
child: FutureBuilder(
future: controller?.getFlashStatus(),
builder: (context, snapshot) {
if (snapshot.data == true) {
return const Icon(Icons.flash_on);
} else {
return const Icon(Icons.flash_off);
}
// Text('Flash: ${snapshot.data}');
},
)),
),
const Padding(padding: EdgeInsets.fromLTRB(37, 0, 0, 0)),
if (result != null)
Text('ID:${result!.code}')
else
const Text('Escanee el QR del producto'),
],
),
),
)
],
),
);
}
Widget buildQrView(BuildContext context) {
// For this example we check how width or tall the device is and change the scanArea and overlay accordingly.
var scanArea = (MediaQuery.of(context).size.width < 400 ||
MediaQuery.of(context).size.height < 400)
? 150.0
: 300.0;
// To ensure the Scanner view is properly sizes after rotation
// we need to listen for Flutter SizeChanged notification and update controller
return QRView(
key: qrKey,
onQRViewCreated: onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.white,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: scanArea),
onPermissionSet: (ctrl, p) => onPermissionSet(context, ctrl, p),
);
}
void onQRViewCreated(QRViewController controller) {
setState(() {
this.controller = controller;
});
controller.scannedDataStream.listen((scanData) {
setState(() {
result = scanData;
});
controller.pauseCamera();
Stream<List<Products>> readProducts() => FirebaseFirestore.instance
.collection('products')
.where('id', isEqualTo: '${result!.code}')
.snapshots()
.map((snapshot) => snapshot.docs
.map((doc) => Products.fromJson(doc.data()))
.toList());
Future<bool> onWillPop() async {
return false;
}
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) => WillPopScope(
onWillPop: () async => false,
child: WillPopScope(
onWillPop: onWillPop,
child: Dialog(
insetPadding: const EdgeInsets.all(8),
child: StreamBuilder<List<Products>>(
stream: readProducts(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Algo ha ocurrido! ${snapshot.error}');
} else if (snapshot.hasData) {
final products = snapshot.data!;
return Container(
margin: const EdgeInsets.all(8),
child: Column(
mainAxisSize: MainAxisSize.min,
children: products
.map((p) => BuildProducts(
products: p, controller: controller))
.toList()),
);
} else {
return const Center(child: CircularProgressIndicator());
}
}),
),
),
),
);
});
}
void onPermissionSet(BuildContext context, QRViewController ctrl, bool p) {
log('${DateTime.now().toIso8601String()}_onPermissionSet $p');
if (!p) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('no Permission')),
);
}
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
}

FutureBuilder operated without initState in flutter

I work with FutureBuilder to view a set of data through GridView by FutureBuilder but there are one problem the data is view without put method in initState().I don't know why it works without putting it in initState().
full code:
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
super.initState();
}
bool showicon = false;
var apiURL;
Future getdataCat() async {
setState(() {
showicon = true;
});
apiURL = '***********************';
var response = await http.post(Uri.parse(apiURL));
var responsebody = jsonDecode(response.body);
if (responsebody.length > 0) {
return responsebody;
} else {
showicon = false;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: <Widget>[
Flexible(
child: FutureBuilder(
future: getdataCat(),
builder: (context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
// still waiting for data to come
return showicon
? Center(
child: CircularProgressIndicator(
color: Colors.black,
))
: SizedBox(
height: 10,
child: Center(
child: Image.asset(
'assets/data.png',
)));
} else if (snapshot.hasData &&
snapshot.data.isEmpty &&
snapshot.data <= 0) {
return SizedBox(
height: 10,
child: Center(
child: Image.asset(
'assets/data.png',
)));
} else {
return GridView.builder(
physics: ScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, childAspectRatio: 3.4),
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Container(
child: Card(
child: Column(
children: <Widget>[
Flexible(
child: GestureDetector(
child: Column(children: <Widget>[
Center(
child: Text(
"${snapshot.data[index]['name']}"))
]),
)),
],
),
),
);
},
);
}
},
),
)
],
),
),
);
}
}
As you can see I not make any thing in initState() but it's still working.
I need to stop it if I don't put it in initState().Because I need to run a different function before it.
I prefer this way. You can check Randal L. Schwartz video
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late final Future<List<int>?> myFuture;
#override
void initState() {
super.initState();
myFuture = getCatData();
}
Future<List<int>?> getCatData() async {
await Future.delayed(Duration(seconds: 2));
//your operations
return [1, 2, 5];
// return [];
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(onPressed: () {
setState(() {});
}),
body: Center(
child: Column(
children: <Widget>[
Flexible(
child: FutureBuilder<List<int>?>(
future: myFuture,
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text("Error ${snapshot.error}");
}
if (!snapshot.hasData) {
return Text("no Data found");
}
if (snapshot.data!.isEmpty) {
return Text("Empty found");
}
if (snapshot.hasData) {
return GridView.builder(
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 3.4,
),
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Container(
child: Text(snapshot.data[index].toString()));
},
);
}
return Text("NA");
},
),
)
],
),
),
);
}
}
Point of FutureBuilder is to run a function that will return with the data you want to use to build your widgets.
You already call your method in the FutureBuilder:
FutureBuilder(
future: getdataCat(),
builder: (context, AsyncSnapshot snapshot) {...}
)

Am Trying To calculate total price of a List of items

am making a shopping cart app where I want to calculate the total price of the products present in the cart I made a function for it and tried executing in init state but it's not working
import 'package:flutter/material.dart';
import 'package:shop/Models/Database.dart';
class Cart extends StatefulWidget {
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
int sum = 0;
total() {
studlist.forEach((element) {
sum = sum + element.price;
});
}
#override
void initState() {
total();
super.initState();
}
final DbStudentManager dbmanager = new DbStudentManager();
Student cart;
List<Cart> cartList;
int updateIndex;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'Cart',
style: TextStyle(color: Colors.black),
),
),
body: FutureBuilder(
future: dbmanager.getStudentList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
studlist = snapshot.data;
}
return ListView.builder(
itemCount: studlist == null ? 0 : studlist.length,
itemBuilder: (BuildContext context, int index) {
Student ct = studlist[index];
return Card(
child: ListTile(
title: Text(ct.name),
subtitle: Text('${ct.price}'),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
dbmanager.deleteStudent(ct.id);
setState(() {
studlist.remove(index);
});
}),
),
);
});
}),
bottomNavigationBar: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Text('$sum'),
SizedBox(
width: 10,
),
Text('Check Out'),
],
),
),
],
),
);
}
}
the error I get:
The method 'forEach' was called on null.
Receiver: null
Tried calling: forEach(Closure: (Student) => Null)
Try this:
import 'package:flutter/material.dart';
import 'package:shop/Models/Database.dart';
class Cart extends StatefulWidget {
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
int sum = 0;
#override
void initState() {
super.initState();
}
final DbStudentManager dbmanager = new DbStudentManager();
Student cart;
List<Cart> studList=[];
int updateIndex;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'Cart',
style: TextStyle(color: Colors.black),
),
),
body: FutureBuilder(
future: dbmanager.getStudentList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
studlist = snapshot.data;
studlist.forEach((element) {
setState((){
sum = sum + element.price;
});
});
}
return ListView.builder(
itemCount: studlist == null ? 0 : studlist.length,
itemBuilder: (BuildContext context, int index) {
Student ct = studlist[index];
return Card(
child: ListTile(
title: Text(ct.name),
subtitle: Text('${ct.price}'),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
dbmanager.deleteStudent(ct.id);
setState(() {
studlist.remove(index);
});
}),
),
);
});
}),
bottomNavigationBar: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Text('$sum'),
SizedBox(
width: 10,
),
Text('Check Out'),
],
),
),
],
),
);
}
}
Try running total() function if the data when the data is loaded, not in init. As data is initially empty, running it inside init will cause this error.
if (snapshot.hasData) {
studlist = snapshot.data;
total();
}
Full Code:
import 'package:flutter/material.dart';
import 'package:shop/Models/Database.dart';
class Cart extends StatefulWidget {
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
int sum = 0;
total() {
studlist.forEach((element) {
sum = sum + element.price;
});
}
final DbStudentManager dbmanager = new DbStudentManager();
Student cart;
List<Cart> cartList;
int updateIndex;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'Cart',
style: TextStyle(color: Colors.black),
),
),
body: FutureBuilder(
future: dbmanager.getStudentList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
studlist = snapshot.data;
total(); //Run the total() function here
}
return ListView.builder(
itemCount: studlist == null ? 0 : studlist.length,
itemBuilder: (BuildContext context, int index) {
Student ct = studlist[index];
return Card(
child: ListTile(
title: Text(ct.name),
subtitle: Text('${ct.price}'),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
dbmanager.deleteStudent(ct.id);
setState(() {
studlist.remove(index);
});
}),
),
);
});
}),
bottomNavigationBar: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Text('$sum'),
SizedBox(
width: 10,
),
Text('Check Out'),
],
),
),
],
),
);
}
}
try this
If I added Quantity increased totalQty but I have one issue if I removing Item in list
did not decrease. sorry my english not good
`total() {
studlist.forEach((element) {
if(element.qty!=null){
totalQty=totalQty+element.qty;
print(totalQty);
}
});
}
`