Flutter List of dynamic checkboxex from API - flutter

I am a learner and new to Flutter.
I want help with the followings
I need to get a list of items with checkboxes from and API
I should be able to select a single or multiple checkboxes
If I select a checkbox its should display the total amount selected
if I select two checkboxes, its should sum the total of the two for me and display it.
Below is what I have done so far.
I will greatly appreciate your solutions
here is my code
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:liquid_pull_to_refresh/liquid_pull_to_refresh.dart';
import 'dart:convert';
import 'dart:ffi';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:stachup/models/TeamModel.dart';
import 'package:stachup/models/newStaches.dart';
import 'package:stachup/models/TeamModel.dart';
class Stash extends StatefulWidget {
String first_name;
String token;
String referalcode;
String last_name;
Stash(
{Key? key,
required this.first_name,
required this.token,
required this.last_name,
required this.referalcode})
: super(key: key);
#override
State<Stash> createState() => _StashState();
}
class _StashState extends State<Stash> {
bool isChecked = false;
String? first_name;
String? token;
String? last_name;
String? referalcode;
bool setup = false;
String? setupError;
bool _isChecked = false;
late SharedPreferences logindata;
userData() async {
logindata = await SharedPreferences.getInstance();
first_name = logindata.getString('first_name')!;
last_name = logindata.getString('last_name')!;
referalcode = logindata.getString('referalcode')!;
token = logindata.getString('token')!;
setState(() {});
}
List<Team> teams = [];
Future getData() async {
var response = await http.get(Uri.https(
'incoming.isplitpay.com', 'api/durationlist', {'token': token}));
var jsonData = jsonDecode(response.body);
print(token);
for (var eachTeam in jsonData) {
var datetime = DateTime.parse(eachTeam["paid_date"]);
final team = Team(
id_pes: eachTeam['id_pes'],
amount: eachTeam['amount'],
paid_date: datetime,
);
teams.add(team);
}
// print(teams.length);
}
#override
void initState() {
super.initState();
userData();
}
#override
Widget build(BuildContext context) {
//getData();
return Scaffold(
backgroundColor: Colors.blue.shade50,
body: FutureBuilder(
future: getData(),
builder: ((context, snapshot) {
//if done loading show data
if (snapshot.connectionState == ConnectionState.done) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
),
child: ListView.builder(
itemCount: teams.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 80,
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
),
color: Colors.grey[50],
borderRadius: BorderRadius.circular(12),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Checkbox(
checkColor: Colors.white,
value: _isChecked,
onChanged: (bool? value) {
setState(() {
_isChecked = value!;
});
print(value);
},
),
Text(
'GHS ' + teams[index].amount,
style: GoogleFonts.lato(
fontSize: 16,
),
),
Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Text(
'Savings for',
style: GoogleFonts.lato(
fontSize: 16,
),
),
),
Text(
"${teams[index].paid_date.day.toString().padLeft(2, '0')}-${teams[index].paid_date.month.toString().padLeft(2, '0')}-${teams[index].paid_date.year}",
style: GoogleFonts.lato(
fontSize: 16,
),
),
],
)
],
),
),
);
}),
);
//else show circule progress bar
} else {
return Center(
child: CircularProgressIndicator(),
);
}
}),
),
);
}
}
My Model
import 'package:flutter/material.dart';
class Team {
final String id_pes;
final String amount;
final DateTime paid_date;
Team({
required this.id_pes,
required this.amount,
required this.paid_date,
});
}
class UserProgress {
final int goaldays;
final double progress;
UserProgress({
required this.goaldays,
required this.progress,
});
}

You can add a variable inside the Class Team to control the CheckBox.
The checked list can be filtered out through the List.where() function.
I added the Tooltip() Widget to show the expected effect.
import 'package:flutter/material.dart';
class MyWidget extends StatefulWidget {
const MyWidget({super.key});
#override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
List<Team> dataList = [
Team(id_pes: '1', amount: '10', paid_date: DateTime.now()),
Team(id_pes: '2', amount: '20', paid_date: DateTime.now()),
Team(id_pes: '3', amount: '30', paid_date: DateTime.now()),
Team(id_pes: '4', amount: '40', paid_date: DateTime.now()),
Team(id_pes: '5', amount: '50', paid_date: DateTime.now()),
Team(id_pes: '6', amount: '60', paid_date: DateTime.now()),
];
Widget _buildListItem(int index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 80,
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
),
color: Colors.grey[50],
borderRadius: BorderRadius.circular(12),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Checkbox(
checkColor: Colors.white,
value: dataList[index].isChecked ?? false,
onChanged: (bool? value) {
setState(() {
dataList[index].isChecked = value;
});
print(value);
},
),
Text(
'GHS ' + dataList[index].amount,
),
],
),
),
);
}
#override
Widget build(BuildContext context) {
var checkedList = dataList.where((data) => data.isChecked ?? false);
var totalAmount = checkedList.isNotEmpty
? 'TotalAmount:${checkedList.reduce((before, after) => Team(amount: '${double.parse(before.amount) + double.parse(after.amount)}', id_pes: '_', paid_date: DateTime.now())).amount} '
: '';
return Scaffold(
body: ListView.builder(
shrinkWrap: true,
itemCount: dataList.length,
itemBuilder: (context, index) {
return Tooltip(
message: totalAmount, child: _buildListItem(index));
}));
}
}
class Team {
final String id_pes;
final String amount;
final DateTime paid_date;
bool? isChecked;
Team({
required this.id_pes,
required this.amount,
required this.paid_date,
this.isChecked,
});
}

Related

Getting the total amount of the checkboxes

I am a beginer to flutter
I am trying to get the total amount of checkboxes after checking it.
First Partof the code is working alright but the second part of the code is where I am having issues.
I want to be able to check the boxes, get the total amount in total checked
Please Help me.
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:liquid_pull_to_refresh/liquid_pull_to_refresh.dart';
import 'dart:convert';
import 'dart:ffi';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:stachup/models/TeamModel.dart';
import 'package:stachup/models/newStaches.dart';
import 'package:stachup/models/TeamModel.dart';
class Stash extends StatefulWidget {
String first_name;
String token;
String referalcode;
String last_name;
Stash(
{Key? key,
required this.first_name,
required this.token,
required this.last_name,
required this.referalcode})
: super(key: key);
#override
State<Stash> createState() => _StashState();
}
class _StashState extends State<Stash> {
bool isChecked = false;
String? first_name;
String? token;
String? last_name;
String? referalcode;
bool setup = false;
String? setupError;
bool _isChecked = false;
late SharedPreferences logindata;
userData() async {
logindata = await SharedPreferences.getInstance();
first_name = logindata.getString('first_name')!;
last_name = logindata.getString('last_name')!;
referalcode = logindata.getString('referalcode')!;
token = logindata.getString('token')!;
setState(() {});
}
List<Team> teams = [];
Future getData() async {
var response = await http.get(Uri.https(
'incoming.isplitpay.com', 'api/durationlist', {'token': token}));
var jsonData = jsonDecode(response.body);
print(token);
for (var eachTeam in jsonData) {
var datetime = DateTime.parse(eachTeam["paid_date"]);
final team = Team(
id_pes: eachTeam['id_pes'],
amount: eachTeam['amount'],
paid_date: datetime,
);
teams.add(team);
}
// print(teams.length);
}
#override
void initState() {
super.initState();
userData();
}
#override
Widget build(BuildContext context) {
//getData();
return Scaffold(
backgroundColor: Colors.blue.shade50,
body: FutureBuilder(
future: getData(),
builder: ((context, snapshot) {
//if done loading show data
if (snapshot.connectionState == ConnectionState.done) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
),
child: ListView.builder(
itemCount: teams.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 80,
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
),
color: Colors.grey[50],
borderRadius: BorderRadius.circular(12),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Checkbox(
checkColor: Colors.white,
value: teams[index].isChecked ?? false,
onChanged: (bool? value) {
setState(() {
teams[index].isChecked = value;
});
print(value);
},
),
Text(
'GHS ' + teams[index].amount,
),
Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Text(
'Savings for',
style: GoogleFonts.lato(
fontSize: 16,
),
),
),
Text(
"${teams[index].paid_date.day.toString().padLeft(2, '0')}-${teams[index].paid_date.month.toString().padLeft(2, '0')}-${teams[index].paid_date.year}",
style: GoogleFonts.lato(
fontSize: 16,
),
),
],
)
],
),
),
);
}),
);
//else show circule progress bar
} else {
return Center(
child: CircularProgressIndicator(),
);
}
}),
),
);
}
}
second part of the code
#override
Widget build(BuildContext context) {
var checkedList = dataList.where((data) => data.isChecked ?? false);
var totalAmount = checkedList.isNotEmpty
? 'TotalAmount:${checkedList.reduce((before, after) => Team(amount: '${double.parse(before.amount) + double.parse(after.amount)}', id_pes: '_', paid_date: DateTime.now())).amount} '
: '';
return Scaffold(
body: ListView.builder(
shrinkWrap: true,
itemCount: dataList.length,
itemBuilder: (context, index) {
return Tooltip(message: totalAmount, child: _buildListItem(index));
}));
}

How to save API data locally in Flutter so that app can work without internet connection?

I'm developing a small Flutter application using https://newsapi.org/ API and Riverpod. I want to make my app work offline (when there is no internet connection). I'm confused in when/where to save the API response and where to retrieve it.
main.dart (EDITED)
import 'package:flutter/material.dart';
import 'package:flutter_pace_stock_internship_task/model/article_model.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'providers/providers.dart';
import 'screens/home_screen.dart';
import 'utility/size_config.dart';
import 'package:hive_flutter/hive_flutter.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Hive.initFlutter();
Hive.registerAdapter(ArticleAdapter());
Hive.registerAdapter(SourceAdapter());
await Hive.openBox('myarticles');
runApp(
ProviderScope(
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
themeMode: ThemeMode.dark,
darkTheme: ThemeData.dark(),
theme: ThemeData(
fontFamily: 'Roboto',
// scaffoldBackgroundColor: scaffoldBgColor,
),
home: const HomeScreen())),
);
}
article_model.dart
import 'package:hive/hive.dart';
part 'article_model.g.dart';
#HiveType(typeId: 0)
class Article {
Article({
this.source,
this.author,
this.title,
this.description,
this.url,
this.urlToImage,
this.publishedAt,
this.content,
});
#HiveField(0)
Source? source;
#HiveField(1)
String? author;
#HiveField(2)
String? title;
#HiveField(3)
String? description;
#HiveField(4)
String? url;
#HiveField(5)
String? urlToImage;
#HiveField(6)
String? publishedAt;
#HiveField(7)
String? content;
factory Article.fromJson(Map<String, dynamic> json) => Article(
source: Source.fromJson(json["source"]),
author: json["author"] ?? '',
title: json["title"] ?? '',
description: json["description"] ?? '',
url: json["url"] ?? '',
urlToImage: json["urlToImage"] ?? '',
publishedAt: json["publishedAt"] ?? '',
content: json["content"] ?? '',
);
Map<String, dynamic> toJson() => {
"source": source!.toJson(),
"author": author ?? '',
"title": title ?? '',
"description": description ?? '',
"url": url ?? '',
"urlToImage": urlToImage ?? '',
"publishedAt": publishedAt ?? '',
"content": content ?? '',
};
}
#HiveType(typeId: 1)
class Source {
Source({
this.id,
this.name,
});
#HiveField(0)
String? id;
#HiveField(1)
String? name;
factory Source.fromJson(Map<String, dynamic> json) => Source(
id: json["id"] ?? '',
name: json["name"] ?? '',
);
Map<String, dynamic> toJson() => {
"id": id ?? '',
"name": name ?? '',
};
}
api_service.dart
import 'dart:convert';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart' as http;
import '../model/article_model.dart';
class ApiService {
final String _endPoint =
'https://newsapi.org/v2/top-headlines?country=in&apiKey=YOUR_API_KEY';
Future<List<Article>> getArticles() async {
http.Response response = await http.get(Uri.parse(_endPoint));
if (response.statusCode == 200) {
final List result = jsonDecode(response.body)["articles"];
return result.map<Article>((e) => Article.fromJson(e)).toList();
} else {
throw Exception(response.reasonPhrase);
}
}
}
final apiProvider = Provider<ApiService>((ref) => ApiService());
I've written the logic for checking whether there is internet connection or not inside providers.dart.
providers.dart
import 'dart:convert';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../model/article_model.dart';
import '../services/api_service.dart';
enum NetworkStatus {
on,
off,
}
class NetworkDetectorNotifier extends StateNotifier<NetworkStatus> {
late NetworkStatus newState;
NetworkDetectorNotifier() : super(NetworkStatus.off) {
Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
switch (result) {
case ConnectivityResult.wifi:
newState = NetworkStatus.on;
break;
case ConnectivityResult.mobile:
newState = NetworkStatus.on;
break;
case ConnectivityResult.none:
newState = NetworkStatus.off;
break;
case ConnectivityResult.bluetooth:
case ConnectivityResult.ethernet:
case ConnectivityResult.vpn:
}
if (newState != state) {
state = newState;
}
});
}
}
final networkCheckProvider =
StateNotifierProvider<NetworkDetectorNotifier, NetworkStatus>(
(_) => NetworkDetectorNotifier());
final articleProvider = FutureProvider<List<Article>>(
(ref) async => await ref.watch(apiProvider).getArticles());
home_screen.dart
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';
import '../constant/constants.dart';
import '../providers/providers.dart';
import '../utility/size_config.dart';
import 'details_screen.dart';
class HomeScreen extends ConsumerWidget {
const HomeScreen({super.key});
#override
Widget build(BuildContext context, WidgetRef ref) {
//SizeConfig().init(context);
final articles = ref.watch(articlesProviderNew);
return Scaffold(
backgroundColor: scaffoldBgColor,
appBar: AppBar(
backgroundColor: appBarColor,
centerTitle: true,
title: const Text('HEADLINES',
style: TextStyle(
fontSize: appBarTitleSize,
color: appBarTitleColor,
fontWeight: FontWeight.w700,
)),
),
body: articles.when(
data: ((articles) => ListView.builder(
// padding: const EdgeInsets.fromLTRB(16, 0.0, 16, 24),
itemCount: articles.length,
itemBuilder: (context, index) {
final article = articles[index];
final date = DateFormat('yy-mm-dd').parse(article.publishedAt!);
return Padding(
padding: const EdgeInsets.only(
top: 16.0, left: 16.0, right: 16.0, bottom: 24.0),
child: SizedBox(
height: SizeConfig.screenHeight * .35,
width: SizeConfig.screenWidth * .75,
child: InkWell(
onTap: (() =>
Navigator.of(context).push(MaterialPageRoute(
builder: ((context) => DetailsScreen(
article: article,
))))),
child: Card(
shape: const RoundedRectangleBorder(),
child: GridTile(
footer: GridTileBar(
backgroundColor: Colors.black.withOpacity(.5),
title: Text(
article.title!,
style: const TextStyle(
fontSize: articleTitleTextSize,
color: articleTitleTextColor,
),
),
subtitle: Text(
'${article.author!}\t\t\t\t$date',
style: const TextStyle(
fontSize: authorTextSize,
color: authorTextColor,
),
),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: CachedNetworkImage(
fit: BoxFit.cover,
errorWidget: (context, url, error) =>
Image.asset('assets/images/no_image.png'),
placeholder: (context, url) => const Center(
child: CircularProgressIndicator()),
imageUrl:
articles.elementAt(index).urlToImage!),
),
),
),
),
),
);
},
)),
error: ((error, stackTrace) {
print('Error : $error\n$stackTrace');
return Text('Error : $error\n$stackTrace');
}),
loading: () => const Center(
child: CircularProgressIndicator(),
),
),
);
}
}
details_screen.dart
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import '../constant/constants.dart';
import '../model/article_model.dart';
import '../utility/size_config.dart';
class DetailsScreen extends StatelessWidget {
const DetailsScreen({Key? key, required this.article}) : super(key: key);
final Article article;
#override
Widget build(BuildContext context) {
return Stack(
children: [
CachedNetworkImage(
height: SizeConfig.screenHeight,
width: SizeConfig.screenWidth,
fit: BoxFit.cover,
errorWidget: (context, url, error) =>
Image.asset('assets/images/no_image.png'),
placeholder: (context, url) =>
const Center(child: CircularProgressIndicator()),
imageUrl: article.urlToImage!),
Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
elevation: 0.0,
backgroundColor: Colors.transparent,
leading: Container(
height: 42.0,
width: 42.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: const Color.fromRGBO(0, 0, 0, 1).withOpacity(.3)),
child: IconButton(
icon: const Icon(
Icons.arrow_back,
size: 42.0,
),
onPressed: () => Navigator.of(context).pop(),
),
)),
body: Padding(
padding: const EdgeInsets.all(leftPadding2),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
article.title!,
style: const TextStyle(
fontSize: appBarTitleSize, color: articleTitleTextColor),
),
const SizedBox(
height: vertPadding,
),
Row(
//mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(article.author!,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: articleTitleTextSize,
color: articleTitleTextColor)),
),
const SizedBox(
width: 10.0,
),
Expanded(
child: Text(article.publishedAt!,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: articleTitleTextSize,
color: articleTitleTextColor)),
),
],
),
const SizedBox(
height: vertPadding2,
),
Text(article.content!,
style: const TextStyle(
fontSize: articleContentSize, color: authorTextColor))
],
),
),
),
],
);
}
}
Can anyone tell me how to make my app work offline ?
Edit-: Following code I'm using for saving and retrieving API data, but I'm getting error while retrieving, that is type 'List' is not a subtype of type 'FutureOr<List>' .
final articlesProviderNew = FutureProvider<List<Article>>((ref) async {
var articleBox = Hive.box('myarticles');
var network = ref.watch(networkCheckProvider);
switch (network) {
case NetworkStatus.on:
{
List<Article> articles = await ref.watch(apiProvider).getArticles();
var articleLS = articleBox.get('articleLS');
if (articleLS == null || articleLS.isEmpty) {
await articleBox.put('articleLS', articles);
}
return articles;
}
case NetworkStatus.off:
{
var articleLS = articleBox.get('articleLS');
return articleLS;
}
}
});
first of all you need to check :
the first time ever you need to force user to have internet.
all data they will be stored in local memory for the first time then if the user will not have internet then you can get data from local memory.
class NetoworkCheck extends ConsumerWidget {
const NetoworkCheck({super.key});
#override
Widget build(BuildContext context, WidgetRef ref) {
SizeConfig().init(context);
var network = ref.watch(networkCheckProvider);
if (network == NetworkStatus.off) {
return const NoNetworkScreen();
}
return const HomeScreen();
}
}
you can check here
and put your code here for storing data
if (network == NetworkStatus.off) {
store all data
return const NoNetworkScreen();
}
don't forget to use async/await mostly it will tike some time to store data

I tried to get data from firestore but display this error "The instance member 'mapRecords' can't be accessed in an initializer. " on Flutter

I tried to get data from firestore but display this error "The instance member 'mapRecords' can't be accessed in an initializer. " on Flutter.
Screenshots of errors
https://drive.google.com/drive/folders/1toBdn9h4-LgBLl5ybG63brgXmk5G0h3F?usp=sharing
my code
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:hexcolor/hexcolor.dart';
import 'package:kathana/utils/config.dart';
import '../screens/wordsBefore18/database/words12model.dart';
class uitry5 extends StatefulWidget {
const uitry5({Key? key}) : super(key: key);
#override
State<uitry5> createState() => _uitry5State();
}
class _uitry5State extends State<uitry5> {
List<String> wordList = [];
Future _fetch = Future(() async {
var records = await FirebaseFirestore.instance.collection('12words').get();
return mapRecords(records);
});
List<Words12> mapRecords(QuerySnapshot<Map<String, dynamic>> records) {
var wordList = records.docs
.map(
(words12) {
print(words12);
return
Words12(
id: words12.id,
wordName: words12['wordName'],
categoryName: words12['categoryName']
);}
.toList();
return wordList;
}
#override
void initState() {
super.initState();
print(wordList);
}
List<String> selectedWord = [];
List<String>? deSelectedWord = [];
#override
Widget build(BuildContext context) {
double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width;
return Scaffold(
body: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(Config.app_background4), fit: BoxFit.fill),
),
child: SafeArea(
child: Center(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 14, right: 0),
child: Column(
children: [
SizedBox(
width: width * 0.94,
height: height * 0.30,
child: Column(
children: <Widget>[
const SizedBox(height: 16),
Wrap(
children: wordList.map(
(word) {
bool isSelected = false;
if (selectedWord!.contains(word)) {
isSelected = true;
}
return GestureDetector(
onTap: () {
if (!selectedWord!.contains(word)) {
if (selectedWord!.length < 50) {
selectedWord!.add(word);
deSelectedWord!.removeWhere(
(element) => element == word);
setState(() {});
print(selectedWord);
}
} else {
selectedWord!.removeWhere(
(element) => element == word);
deSelectedWord!.add(word);
setState(() {
// selectedHobby.remove(hobby);
});
print(selectedWord);
print(deSelectedWord);
}
},
child: Container(
margin: const EdgeInsets.symmetric(
horizontal: 5, vertical: 4),
child: Container(
padding: const EdgeInsets.symmetric(
vertical: 5, horizontal: 12),
decoration: BoxDecoration(
color: isSelected
? HexColor('#0000FF')
: HexColor('#D9D9D9'),
borderRadius:
BorderRadius.circular(18),
border: Border.all(
color: isSelected
? HexColor('#0000FF')
: HexColor('#D9D9D9'),
width: 2)),
child: Text(
word,
style: TextStyle(
color: isSelected
? Colors.black
: Colors.black,
fontSize: 14,
fontWeight: FontWeight.w600),
),
),
),
);
},
).toList(),
),
],
),
),
],
),
),
],
))),
),
);
}
}
model
import 'dart:convert';
Words12 words12FromJson(String str) => Words12.fromJson(json.decode(str));
String words12ToJson(Words12 data) => json.encode(data.toJson());
class Words12 {
Words12({
required this.id,
required this.wordName,
required this.categoryName,
});
String id;
String wordName;
String categoryName;
factory Words12.fromJson(Map<String, dynamic> json) => Words12(
id: json["id"],
wordName: json["wordName"],
categoryName: json["categoryName"],
);
Map<String, dynamic> toJson() => {
"id": id,
"wordName": wordName,
"categoryName": categoryName,
};
}
How do I resolve this and get data from the database
You can use late before future.
late Future _fetch = ...
Also I will prefer shifting mapRecords before _fetch and FutureBuilder for future.

After get request, data isn't showing in my screen

In this code data successfully adding to my ''items'' list.
But In the second code, when I call my ''items'' list, It looks empty. What should I do for displaying data?
import 'dart:convert';
import 'package:http/http.dart' as http;
class IceCream {
final String id;
final String? title;
final String? shortTitle;
final String? description;
final String? longDescription;
final double price;
final String imageUrl;
final double? kilos;
final double? review;
final int? reviewCount;
IceCream(
{required this.id,
this.title,
this.shortTitle,
this.description,
this.longDescription,
required this.price,
required this.imageUrl,
this.kilos,
this.review,
this.reviewCount});
}
class Products {
List<IceCream> _items = [];
List<IceCream> get items {
return [..._items];
}
Future<void> fetchProducts() async {
final url = Uri.parse(
'https://ice-cream-app-31dce-default-rtdb.europe-west1.firebasedatabase.app/icecreams.json');
try {
final response = await http.get(url);
// print(response.body);
final extractedData = json.decode(response.body) as Map<String, dynamic>;
if (extractedData.length == null) {
return;
}
final List<IceCream> loadedProduct = [];
extractedData.forEach((prodId, prodData) {
loadedProduct.add(IceCream(
id: prodId,
title: prodData['title'],
description: prodData['description'],
price: prodData['price'],
imageUrl: prodData['imageUrl'],
shortTitle: prodData['shortTitle'],
longDescription: prodData['longDescription'],
kilos: prodData['kilos'],
review: prodData['review'],
reviewCount: prodData['reviewCount']));
});
_items = loadedProduct;
//print(items);
} catch (error) {
print(error);
throw (error);
}
}
}
Second code:
import 'package:flutter/material.dart';
import 'package:ice_cream_ui_clone/model/ice_cream.dart';
import 'package:ice_cream_ui_clone/screens/detail_screen.dart';
import '../utils/constants.dart';
import 'add_item_button.dart';
class TopFlavoursList extends StatelessWidget {
#override
Widget build(BuildContext context) {
final cart = Products().items;
return Expanded(
flex: 2,
child: ListView.builder(
itemCount: cart.length,
scrollDirection: Axis.horizontal,
itemBuilder: (ctx, i) => GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (ctx) => DetailScreen(
item: cart[i],
)));
},
child: Card(
color: myLightPinkColor,
child: Padding(
padding: EdgeInsets.all(lowPadding),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Image.network(
cart[i].imageUrl,
height: midImageHeight,
width: midImageWidht,
),
SingleChildScrollView(
child: Column(
children: [
Text(cart[i].title!,
style:
Theme.of(context).textTheme.headline5),
SizedBox(
height: lowPadding,
),
Row(
children: [
Text("${cart[i].kilos.toString()} KG",
style: Theme.of(context)
.textTheme
.headline6),
SizedBox(
width: lowImageWidht,
),
Icon(
Icons.star,
color: myYellowColor,
),
Text(cart[i].review.toString(),
style: Theme.of(context)
.textTheme
.headline6)
],
),
Row(
children: [
Text("\$${cart[i].price.toString()}",
style: Theme.of(context)
.textTheme
.headline5),
SizedBox(
width: lowImageWidht,
),
AddItemButton(
buttonShape: const CircleBorder(),
)
],
)
],
),
)
],
)),
),
)),
);
}
}
I think the issue is with the "forEach" statment. Should be something more like
extractedData.forEach((data) {
loadedProduct.add(IceCream())
});
The function in the forEach should take one argument not 2

How to read nested data with firestore in flutter?

I am display a list of products, searched plenty of articles and tutorials but didn't succeeded to display the list of units fetched from the firestore and the specific price of the unit from firestore. kindly help me to achieve it.
I want to display the unit in a dropdown list and the assigned price according to the unit, but unable to do so, as i am new to flutter and trying to do code with the help of tutorials.
product.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class Product with ChangeNotifier {
final String id;
final String title;
final String description;
final String imageUrl;
final String productCategoryName;
Product({
required this.id,
required this.title,
required this.description,
required this.imageUrl,
required this.productCategoryName,
});
}
class ProductProvider with ChangeNotifier {
List<Product> _products = [];
Future<void> fetchProducts() async {
await FirebaseFirestore.instance
.collection('products')
.get()
.then((QuerySnapshot productSnapshot) {
_products = [];
for (var element in productSnapshot.docs) {
_products.insert(
0,
Product(
id: element.data()['productId'],
title: element.data()['productTitle'],
description: element.data()['productDescription'],
imageUrl: element.data()['productImage'],
productCategoryName: element.data()['productCategory'],
),
);
}
});
}
List<Product> products() => _products;
List<Product> getByCatName(String catName) {
List<Product> catList = _products
.where((element) =>
element.productCategoryName.toLowerCase() == catName.toLowerCase())
.toList();
return catList;
}
Product getById(String prodId) {
return _products.firstWhere((element) => element.id == prodId);
}
List<Product> getBySearch(String search) {
List<Product> prodList = _products
.where((element) =>
element.title.toLowerCase().contains(search.toLowerCase()))
.toList();
notifyListeners();
return prodList;
}
}
feed_product.dart
import 'dart:io';
import 'package:badges/badges.dart';
import 'feed_product_dialog.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models_providers/product.dart';
import '../screens/inner_screens/product_details_screen.dart';
class FeedsProduct extends StatefulWidget {
const FeedsProduct({Key? key}) : super(key: key);
#override
_FeedsProductState createState() => _FeedsProductState();
}
class _FeedsProductState extends State<FeedsProduct> {
String unitValue = '1kg';
late Product product;
#override
Widget build(BuildContext context) {
final productAttribute = Provider.of<Product>(context);
return InkWell(
onTap: () {
Navigator.of(context).pushNamed(
ProductDetailsScreen.routeName,
arguments: productAttribute.id,
);
},
child: Stack(
children: \[
Container(
height: 300,
decoration: BoxDecoration(
border: Border.all(width: 1, color: Colors.black),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: \[
Center(
child: Container(
constraints: BoxConstraints(
minHeight: Platform.isIOS ? 170 : 140,
maxHeight: MediaQuery.of(context).size.height * 0.21),
child: Center(
child: Image.network(productAttribute.imageUrl,
fit: BoxFit.cover),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: \[
Text(
productAttribute.title,
maxLines: 1,
style: const TextStyle(
fontSize: 16,
overflow: TextOverflow.ellipsis,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: \[
DropdownButton<String>(
value: unitValue,
elevation: 16,
style: const TextStyle(color: Colors.black),
onChanged: (String? newValue) {
setState(() {
unitValue = newValue!;
});
},
items: <String>\['500gm', '1kg'\]
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
IconButton(
onPressed: () async {
return showDialog(
context: context,
builder: (ctx) => FeedsProductDialog(
product: productAttribute,
),
);
},
icon: const Icon(Icons.more_horiz),
),
\],
),
\],
),
)
\],
),
),
Badge(
toAnimate: true,
animationType: BadgeAnimationType.slide,
shape: BadgeShape.square,
badgeColor: Colors.deepOrange,
borderRadius: BorderRadius.circular(8),
badgeContent:
const Text('New', style: TextStyle(color: Colors.white)),
),
\],
),
);
}
}