Update an item on a list in my flutter app without having same item with updated value - flutter

When I run the code, the list adds another item instead of updating the old item (still displaying the old item) which the index was found. I have also tried as using keys on my listView.builder() listView.custom(), and on the Custom Widget I created which renders on the listView.builder() all give same result. Is there something I'm not doing right?
using the indexWhere() this way,
void updateProduct(String id, ProductSaver productSaver) {
final prodIndex = _productList.indexWhere((element) => element.id == id);
final newProduct = ProductSaver(
title: productSaver.title,
description: productSaver.description,
imageUrl: productSaver.imageUrl,
price: productSaver.price);
_productList[prodIndex] = newProduct as Product;
notifyListeners();
}
and this way:
void updateProduct(String id, Product newItem){
final pIndex = _productList.indexWhere((element)=>element.id == id);
if(pIndex >= 0){
_productList[pIndex] = newItem;}
notifyListeners();}
I also used the list.contain()
void updateProduct({String? id, required Product newItem}) {
final itemIndex = _productList.indexWhere((prod) => prod.id! == id);
if (_productList.contains(_productList[itemIndex])) {
_productList[itemIndex] = newItem;
}
notifyListeners();
}
Here is the build() of the code:
#override
Widget build(BuildContext context) {
final providerData = Provider.of<Products>(context);
return Scaffold(
appBar: AppBar(
title: const Text('Products'),
actions: [
IconButton(
onPressed: () {
Navigator.of(context).pushNamed(EditProductScreen.routeName);
},
icon: const Icon(
Icons.add,
size: 30,
),
)
],
backgroundColor: MyColor.primaryColor,
),
body: ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 10),
itemCount: providerData.item.length,
itemBuilder: (context, index) {
return Column(
children: [
UserProductItem(
id: providerData.item[index].id!,
imageUrl: providerData.item[index].imageUrl,
title: providerData.item[index].title),
)
],
);
}),
);
}
}
the above UserProductItem() Widget.
class UserProductItem extends StatelessWidget {
const UserProductItem({
Key? key,
required this.imageUrl,
required this.title,
required this.id,
}) : super(key: key);
final String imageUrl;
final String title;
final String? id;
#override
Widget build(BuildContext context) {
final productData = Provider.of<Products>(context);
return ListTile(
key: UniqueKey(),
leading: Image.network(
imageUrl,
),
title: Text(
title,
style: const TextStyle(
color: MyColor.primaryColor,
fontSize: 17,
),
),
trailing: FittedBox(
child: Row(
children: [
IconButton(
icon: const Icon(
Icons.edit,
color: Colors.green,
),
onPressed: () {
Navigator.of(context)
.pushNamed(EditProductScreen.routeName, arguments: id!);
},
),
IconButton(
icon: const Icon(
Icons.delete_outline_outlined,
color: Colors.red,
),
onPressed: () {
productData.removeItem(id!);
},
),
],
),
),
);
}
}

You changed the value at a specific index. Instead you can try adding an item to the list
if (_productList.contains(_productList[itemIndex])) {
_productList.add(newItem);//<--here
}

Related

Add Textfield to ListView and multiply the value of that textfield by the a price of that item

I have a shopping app, Using Provider I am able to create a list of Cart items. Based on the price and the quantity from each item, a grand total is calculated. I want the user to enter their own quantity.
Here is my CartScreen
Widget build(BuildContext context) {
final cart = Provider.of<Cart>(context);
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text("Items Purchased"),
),
body: Column(
children: <Widget>[
Card(
margin: EdgeInsets.all(15),
child: Padding(
padding: EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'Total',
style: TextStyle(
fontSize: 20,
),
),
Spacer(),
Chip(
label: Text(
'GHC ${cart.totalAmount}',
style: TextStyle(
color: Colors.white,
),
),
backgroundColor: Colors.redAccent,
),
FlatButton(
onPressed: () {
print(cart);
// Provider.of<Orders>(context).addOrder(
// cart.items.values.toList(), cart.totalAmount);
// cart.clear();
},
child: Text("CONFIRM"),
),
],
),
),
),
SizedBox(
height: 10,
),
Expanded(
child: ListView.builder(
itemCount: cart.itemCount,
itemBuilder: (ctx, i) => CartItemWidget(
cart.items.values.toList()[i].id,
cart.items.keys.toList()[i],
cart.items.values.toList()[i].price,
TextField(
controller: _controllers[i],
onChanged: (value) {
final x = double.tryParse(value);
setState(() {
itemTotal = x ?? 0;
itemTotal = cart.items.values.toList()[i].price * x;
print(itemTotal);
});
},
),
cart.items.values.toList()[i].quantity,
cart.items.values.toList()[i].title,
cart.items.values.toList()[i].image),
),
),
],
),
);
}
I think the calculation should be at the CartItemWidget instead.
class CartItemWidget extends StatelessWidget {
final String id;
final String productId;
final double price;
final Widget quantityField;
final int quantity;
final String title;
final String image;
CartItemWidget(this.id, this.productId, this.price, this.quantityField,
this.quantity, this.title, this.image);
#override
Widget build(BuildContext context) {
return Dismissible(
key: ValueKey(id),
direction: DismissDirection.endToStart,
background: Container(
color: Theme.of(context).errorColor,
child: Icon(
Icons.delete,
color: Colors.white,
size: 40,
),
alignment: Alignment.centerRight,
padding: EdgeInsets.only(right: 20),
margin: EdgeInsets.symmetric(horizontal: 15, vertical: 4),
),
onDismissed: (direction) {
Provider.of<Cart>(context, listen: false).removeItem(productId);
},
child: Card(
margin: EdgeInsets.symmetric(
horizontal: 15,
vertical: 4,
),
child: Padding(
padding: EdgeInsets.all(8),
child: ListTile(
leading: CircleAvatar(
child: FittedBox(child: Image.asset(image)),
backgroundColor: Colors.black38,
),
title: Text(title),
subtitle: Text('Total: GHC ${(price * quantity)}'),
trailing: Container(width: 70.0, child: TextField()),
// trailing: Text('$quantity X'),
),
),
),
);
}
}
I have a Model class with Provider too.
class CartItem with ChangeNotifier {
final String id;
final String title;
final int quantity;
final double price;
final String image;
CartItem(
{#required this.id,
#required this.title,
#required this.quantity,
#required this.price,
this.image});
}
class Cart with ChangeNotifier {
Map<String, CartItem> _items = {};
Map<String, CartItem> get items {
return {..._items};
}
int get itemCount {
return _items.length;
}
double get totalAmount {
double total = 0.0;
_items.forEach((key, cartItem) {
total += cartItem.price * cartItem.quantity;
});
return total;
}
double get totalForEachItem {
double total = 0.0;
_items(key, cartItem) {
total = cartItem.price * cartItem.quantity;
}
}
void addItems(String productId, double price, String title, String image) {
if (_items.containsKey(productId)) {
//change quantity
_items.remove(productId);
// clear();
} else {
_items.putIfAbsent(
productId,
() => CartItem(
id: DateTime.now().toString(),
title: title,
price: price,
quantity: 1,
image: image),
);
}
notifyListeners();
}
void removeItem(String productId) {
_items.remove(productId);
notifyListeners();
}
void getItemTotal(String productId, double price, int quantity) {}
void clear() {
_items = {};
notifyListeners();
}
}
What I want
Currently the product details such as name, price and quantity are passed from the products page. I want the user to enter their own quantity and total will automatically update by multiplying the quantity entered for cartItem[i] by the price at cartItem[i] and add the total for each item for the grandtotal.
What I have done
I created a list of controllers so i can get the values at each cartitem. I also used the onChange to get the value to multiply the price and set a total with that.
Create a void function (use a setter type function set )that sets the quantity of the item. then tie the onSubmitted parameter (or however you're receiving the data) of textField with the setter function of the provider.
Now the setter function sets the new value for the quantity of the product and rebuilds the rest of the widgets.
I may not be able to correctly drop you the code, but you could get some help with my idea.
Happy to help :)

how to display data in flutter firestore provider

I want to display data from firestore using provider in flutter. i got stuck please help. below are my codes
//product display page
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shopping/pages/product_details.dart';
import 'package:shopping/provider/app_provider.dart';
class Product extends StatefulWidget {
#override
_ProductState createState() => _ProductState();
}
class _ProductState extends State<Product> {
#override
Widget build(BuildContext context) {
final product = Provider.of<AppProvider>(context);
return GridView.builder(
itemCount: productList.length,
gridDelegate:new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2),
itemBuilder: (BuildContext context, int index){
return Padding(
padding:const EdgeInsets.all(4.0),
child:SingleProd(
//where i want to get the product details
prodName: product.featuredProducts[index].name.toString(),
),
);
}
);
}
}
class SingleProd extends StatelessWidget {
final prodName;
final prodPicture;
final prodOldPrice;
final prodPrice;
SingleProd({this.prodName, this.prodPicture,this.prodOldPrice,this.prodPrice});
#override
Widget build(BuildContext context) {
return Card(
child: Hero(tag: new Text("hero 1"),
child:
Material( child: InkWell(
onTap: ()=>Navigator.of(context).push(new MaterialPageRoute(builder: (context)=>ProductDetails(
//here we are passing the value of the products to Product detail page
productDetailName:prodName,
)
)
),
child:GridTile(
footer: Container(
color: Colors.white,
child: new Row(
children: <Widget>[
new Expanded(
child: new Text(prodName, style: TextStyle(fontWeight: FontWeight.bold, fontSize:16.0),),
),
new Text(
"\$$prodPrice", style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold),)
],
)
),
child: Image.asset(prodPicture,
fit: BoxFit.cover,),
),
),
),
),
);
}
}
//product class
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/foundation.dart';
class Product{
static const ID = "id";
static const CATEGORY = "category";
static const NAME = "name";
static const PRICE = "price";
static const BRAND = "brand";
static const COLORS = "colors";
static const QUANTITY = "quantity";
static const SIZES = "sizes";
static const SALE = "sale";
static const FEATURED = "featured";
static const PICTURE = "picture";
String _id;
String _name;
String _brand;
String _category;
String _picture;
double _price;
int _quantity;
List _colors;
List _sizes;
bool _onSale;
bool _featured;
// getters
String get name => _name;
String get id => _id;
String get category => _category;
String get brand => _brand;
String get picture => _picture;
double get price => _price;
int get quantity => _quantity;
List get colors => _colors;
List get sizes => _sizes;
bool get onSale => _onSale;
bool get featured => _featured;
// named constructure
Product.fromSnapshot(DocumentSnapshot snapshot){
Map data = snapshot.data;
_name = data[NAME];
_id = data[ID];
_category = data[CATEGORY];
_brand = data[BRAND];
_price = data[PRICE];
_quantity = data[QUANTITY];
_colors = data[COLORS];
_onSale = data[SALE];
_featured = data[FEATURED];
_picture = data[PICTURE];
}
}
//provider page for the product
import 'package:flutter/material.dart';
import 'package:shopping/db/product.dart';
import 'package:shopping/models/product.dart';
class AppProvider with ChangeNotifier {
List<Product>_fearturedProducts=[];
//method
void _getFeaturedProducts()async{
_fearturedProducts=await _productService.getFeaturedProducts();
notifyListeners();
}
}
//connection to Firestore to collect data
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:shopping/models/product.dart';
class ProductService{
Firestore _firestore=Firestore.instance;
String collection="Products";
Future<List<Product>>getFeaturedProducts(){
_firestore.collection(collection).where('featured', isEqualTo:true).getDocuments()
.then((snap){
List<Product>featuredProducts=[];
snap.documents.map((snapshot)=> featuredProducts.add(Product.fromSnapshot(snapshot)));
return featuredProducts;
});
}
}
guys, I have managed to solve the question. The answer is as follow //product page
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shopping/pages/product_details.dart';
import 'package:shopping/provider/app_provider.dart';
import 'package:shopping/models/product.dart';
class Products extends StatefulWidget {
#override
ProductsState createState() => ProductsState();
}
class ProductsState extends State<Products> {
List<Product> products;
#override
Widget build(BuildContext context) {
final productProvider = Provider.of<CRUDModel>(context);
return StreamBuilder<QuerySnapshot>(
stream: productProvider.fetchProductsAsStream(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasData) {
products = snapshot.data.documents
.map((doc) => Product.fromMap(doc.data, doc.documentID))
.toList();
return GridView.builder(
itemCount: products.length,
gridDelegate:new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2),
itemBuilder: (BuildContext context, index){
return Padding(
padding:const EdgeInsets.all(4.0),
child:SingleProd(
product:products[index]
// prodPicture: productList[index]['picture'],
//prodOldPrice: productList[index]['oldPrice'],
//prodPrice: productList[index]['price'],
),
);
}
);
}
else {
return Text('fetching');
}
}
);
}
}
class SingleProd extends StatelessWidget {
//final prodName;
//final prodPicture;
//final prodOldPrice;
//final prodPrice;
final Product product;
SingleProd({ #required this.product});
//SingleProd({product.picture});
#override
Widget build(BuildContext context) {
return Card(
child: Hero(tag: product.id,
child:
Material( child: InkWell(
onTap: ()=>Navigator.of(context).push(new MaterialPageRoute(builder: (context)=>ProductDetails(
//here we are passing the value of the products to Product detail page
productDetailName:product.name,
productDetailNewPrice:product.price,
productDetailPicture:product.picture,
//productDetailOldPrice:prodOldPrice,
//productDetailNewPrice:prodPrice,
//productDetailPicture: prodPicture,
)
)
),
child:GridTile(
footer: Container(
color: Colors.white,
child: new Row(
children: <Widget>[
new Expanded(
child: new Text(product.name, style: TextStyle(fontWeight: FontWeight.bold, fontSize:16.0),),
),
new Text(
'${product.price} \$', style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold),)
],
)
),
child: Image.asset('assets/${product.picture}.jpg',
fit: BoxFit.cover,),
),
),
),
),
);
}
}
//product class
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:ui';
class Product {
String id;
String name;
String brand;
String category;
String picture;
double price;
int quantity;
List colors;
List sizes;
bool sale;
bool featured;
Product(
{this.id, this.name, this.brand,
this.category, this.picture,this.price,
this.quantity,this.colors,this.sizes,this.sale,this.featured}
);
Product.fromMap(Map snapshot,String id) :
id = id ?? '',
name= snapshot['name'] ?? '',
brand = snapshot['brand'] ?? '',
category = snapshot['category'] ?? '',
picture= snapshot['picture'] ?? '',
price= snapshot['price'] ?? '',
quantity= snapshot['quantity'] ?? '',
colors= snapshot['colors'] ?? '',
sizes= snapshot['sizes'] ?? '',
sale= snapshot['sale'] ?? '',
featured= snapshot['featured'] ?? '';
toJson() {
return {
"name": name,
"brand": brand,
"category": category,
"picture": picture,
"price": price,
"quantity": quantity,
"colors": colors,
"sizes": sizes,
"sale": sale,
"featured": brand,
};
}
}
//provider class for the product
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:shopping/db/Api.dart';
import 'package:shopping/models/product.dart';
class CRUDModel extends ChangeNotifier {
//Api _api = locator<Api>();
String path="Products";
Api _api= Api();
List<Product> products;
Future<List<Product>> fetchProducts() async {
var result = await _api.getDataCollection();
products = result.documents
.map((doc) => Product.fromMap(doc.data, doc.documentID))
.toList();
notifyListeners();
return products;
}
Stream<QuerySnapshot> fetchProductsAsStream() {
notifyListeners();
return _api.streamDataCollection();
}
Future<Product> getProductById(String id) async {
var doc = await _api.getDocumentById(id);
notifyListeners();
return Product.fromMap(doc.data, doc.documentID) ;
}
}
//connection to firestore
import 'package:cloud_firestore/cloud_firestore.dart';
class Api{
final Firestore _db = Firestore.instance;
String ref="Products";
//CollectionReference ref;
/*Api({this.path } ) {
ref = _db.collection(path);
}*/
Future<QuerySnapshot> getDataCollection() {
//return ref.getDocuments() ;
return _db.collection(ref).where('featured', isEqualTo:true).getDocuments();
}
Stream<QuerySnapshot> streamDataCollection() {
// return ref.snapshots() ;
//return _db.snapshots(ref).getDocuments();
return _db.collection(ref).snapshots();
}
Future<DocumentSnapshot> getDocumentById(String id) {
// return ref.document(id).get();
return _db.document(id).get();
}
Future<void> removeDocument(String id){
//return ref.document(id).delete();
return _db.document(id).delete();
}
Future<DocumentReference> addDocument(Map data) {
// return ref.add(data);
return _db.collection(ref).add(data);
}
Future<void> updateDocument(Map data , String id) {
//return ref.document(id).updateData(data) ;
return _db.document(ref).updateData(data);
}
}
//homepage where i displayed the products
import 'package:flutter/material.dart';
import 'package:carousel_pro/carousel_pro.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:shopping/commons/common.dart';
import 'package:provider/provider.dart';
import 'package:shopping/provider/app_provider.dart';
import '../provider/user_provider.dart';
//My packages imports
import 'package:shopping/componets/horizontal_listview.dart';
import 'package:shopping/componets/product.dart';
import 'package:shopping/pages/cart.dart';
import 'package:shopping/pages/login.dart';
class HomePage extends StatefulWidget {
// List<Product> products;
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
TextEditingController _searchController = new TextEditingController();
//final FirebaseAuth _firebaseAuth=FirebaseAuth.instance;
#override
Widget build(BuildContext context) {
final user = Provider.of<UserProvider>(context);
final productProvider=Provider.of<CRUDModel>(context);
Widget image_carousel = new Container(
height: 200.0,
child: new Carousel(
boxFit: BoxFit.cover,
images: [
AssetImage('images/c1.jpg'),
AssetImage('images/m1.jpeg'),
AssetImage('images/m2.jpg'),
AssetImage('images/w1.jpeg'),
AssetImage('images/w3.jpeg'),
AssetImage('images/w4.jpeg'),
],
autoplay:true,
animationCurve: Curves.fastOutSlowIn,
animationDuration: Duration(milliseconds:1000 ),
dotSize: 4.0,
indicatorBgPadding: 8.0,
dotBgColor: Colors.transparent,
),
);
return Scaffold(
appBar: new AppBar(
iconTheme: IconThemeData(color: blue),
elevation: 0.1,
backgroundColor: white,
title: Material(
borderRadius: BorderRadius.circular(20),
color: Colors.grey[50],
elevation: 0.0,
child: TextFormField(
controller: _searchController,
decoration: InputDecoration(
hintText: "Search",
border: InputBorder.none,
),
validator: (value) {
if (value.isEmpty) {
return "The Search field cannot be empty";
}
return null;
}),
),
actions: <Widget>[
new IconButton(
icon: Icon(
Icons.search,
color: blue,
),
onPressed: () {},
),
new IconButton(
icon: Icon(
Icons.shopping_cart,
color: blue,
),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => new Cart()));
}),
],
),
drawer: new Drawer(
child: new ListView(
children: <Widget>[
//drawer header
new UserAccountsDrawerHeader(
accountName: Text("Afolabi"),
accountEmail: Text("mtreal62#gmail.com"),
currentAccountPicture: GestureDetector(
child: new CircleAvatar(
backgroundColor: Colors.grey,
child: Icon(
Icons.person,
color: Colors.white,
),
),
),
decoration: BoxDecoration(
color: blue,
),
),
//body
InkWell(
onTap: () {},
child: ListTile(
title: Text("Home Page"),
leading: Icon(
Icons.home,
color: blue,
),
),
),
InkWell(
onTap: () {},
child: ListTile(
title: Text("My Account"),
leading: Icon(
Icons.person,
color: blue,
),
),
),
InkWell(
onTap: () {},
child: ListTile(
title: Text("My Orders"),
leading: Icon(
Icons.shopping_basket,
color: blue,
),
),
),
InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => new Cart()));
},
child: ListTile(
title: Text("Shopping Cart"),
leading: Icon(
Icons.shopping_cart,
color: blue,
),
),
),
InkWell(
onTap: () {},
child: ListTile(
title: Text("Favourites"),
leading: Icon(
Icons.favorite,
color: blue,
),
),
),
Divider(),
InkWell(
onTap: () {},
child: ListTile(
title: Text("Settings"),
leading: Icon(
Icons.settings,
),
),
),
InkWell(
onTap: () {},
child: ListTile(
title: Text("About"),
leading: Icon(
Icons.help,
),
),
),
InkWell(
onTap: () {
user.signOut();
// changeScreenReplacement(context, Login());
},
child: ListTile(
title: Text("Log Out"),
leading: Icon(
Icons.transit_enterexit,
),
),
),
],
),
),
body: new Column(
children: <Widget>[
//Image Carousel for the home Page Banner
image_carousel,
//padding widget after carousel
new Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
alignment: Alignment.centerLeft,
child: new Text("Categories"),
),
),
//Horizontal layout start from here
HorizontalList(),
//End of the horizontal layout
//padding widget for Recent products categories
new Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
alignment: Alignment.centerLeft,
child: new Text("Recent Products"),
),
),
// Text(appProvider.featuredProducts.length.toString(),
//style: TextStyle(color: Colors.black),),
Flexible(
child: Products(),
),
//Horizontal layout start from here
],
),
);
}
}
Future _signOut() async {
try {
await FirebaseAuth.instance.signOut();
} catch (e) {
print(e); // TODO: show dialog with error
}
}
You are never calling _getFeaturedProducts() from your AppProvider class. So _fearturedProducts will always be null
In class AppProvider you are calling method on undefined name:
_productService.getFeaturedProducts()
Every IDE should show you this error ex. In my Android Studio it looks like this:

Flutter Firebase RTDB issue retrieving specific child

I have tried to retrieve data from a specific child from Firebase RTDB. The problem is that the following error appears (I don't use int):
Unhandled Exception: type 'String' is not a subtype of type 'int' of 'index'
The log says that the error appears here
DATA[individualKey]['name'],
DATA[individualKey]['picture'],
DATA[individualKey]['price'],
DATA[individualKey]['id'],
DATA[individualKey]['brand'],
DATA[individualKey]['category'],
// DATA[individualKey]['feature'],
// DATA[individualKey]['sale'],
// DATA[individualKey]['colors'],
// DATA[individualKey]['sizes'],
DATA[individualKey]['quantity'],
The code that I am going to show, I use it on another screen with minimal changes and it works
but in the current one that I use it doesn't work
class PostsDetails extends StatefulWidget {
final value2;
PostsDetails({Key key,#required this.value2}) : super(key : key);
#override
_PostsDetailsState createState() => _PostsDetailsState(value2);
}
class _PostsDetailsState extends State<PostsDetails> {
final value2;
_PostsDetailsState(this.value2);
List<Posts>postsList = [];
#override
void initState() {
// TODO: implement initState
super.initState();
DatabaseReference postsRef = FirebaseDatabase.instance.reference().child("Product").child("Shoes").child("Nike").child(value2);
postsRef.once().then((DataSnapshot snap)
{
var KEYS = snap.value.keys;
var DATA = snap.value;
postsList.clear();
for(var individualKey in KEYS)
{
Posts posts = new Posts
(
DATA[individualKey]['name'],
DATA[individualKey]['picture'],
DATA[individualKey]['price'],
DATA[individualKey]['id'],
DATA[individualKey]['brand'],
DATA[individualKey]['category'],
// DATA[individualKey]['feature'],
// DATA[individualKey]['sale'],
// DATA[individualKey]['colors'],
// DATA[individualKey]['sizes'],
DATA[individualKey]['quantity'],
);
postsList.add(posts);
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.1,
backgroundColor: Colors.red,
title: InkWell(
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context)=> new HomePage()));
},
child: Text("SHOP APP")),
actions: <Widget>[
new IconButton(icon: Icon(Icons.search, color: Colors.white,), onPressed: (){}),
],
),
body: new ListView(
children: <Widget>[
new Container(
child: postsList.length == 0 ? new Text("No Available"):new ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: postsList.length,
itemBuilder: (_, index){
new Container(
height: 300.0,
child: GridTile(
child: Container(
color: Colors.white,
// child: Image.network(postsList[index].picture),
),
footer: new Container(
color: Colors.white70,
child: ListTile(
leading: new Text(postsList[index].name,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0),),
title: new Row(
children: <Widget>[
Expanded(
// child: new Text("\$"+postsList[index].price, style: TextStyle(fontWeight: FontWeight.bold, color: Colors.red),)
),
],
),
),
),
),
);
})
),
]
)
);
}
}
postslist.length retrieves 0.
final value2 its a child ID. I have verified that it is received well from the previous screen
and if value2 is not used, data will not be retrieved
Posts Class:
class Posts
{
String name;
String picture;
String price;
String id;
String brand;
String category;
String quantity;
// List<> colors;
// List<> sizes;
// bool feature;
// bool sale;
Posts(this.name, this.picture, this.price, this.id, this.category,this.brand,this.quantity);
}
How could it be solved or is there some way to retrieve a specific child? I know how to show a list but not of a specific child thanks
i fixed it, by some reason the code
postsList.length == 0 ? new Text("No Available"):
was the problem so i deleted it

how to make specific search by user in flutter

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'),
),
],
),
),
),
),
);
}
}

Search Items are not showing up during search in SearchBar in Flutter?

I want to add Search Bar in Flutter. And I have achieved the state where I can type content in the search bar but during writing the query the List is not updating.
I want to sort on basis of blogName and below is the code
class AllBlogs extends StatefulWidget {
AllBlogs({Key key}) : super(key: key);
final Color _tabBackgroudColor = const Color(0xFF1A237E);
#override
AllBlogsState createState() {
return new AllBlogsState();
}
}
class AllBlogsState extends State<AllBlogs> {
Widget appBarTitle = Text("Blog's List");
Icon actionIcon = Icon(Icons.search, color: Colors.white,);
final key = new GlobalKey<ScaffoldState>();
final TextEditingController _searchQuery = new TextEditingController();
bool _IsSearching;
String _searchText = "";
_SearchListState() {
_searchQuery.addListener(() {
if (_searchQuery.text.isEmpty) {
setState(() {
_IsSearching = false;
_searchText = "";
});
}
else {
setState(() {
_IsSearching = true;
_searchText = _searchQuery.text;
});
}
});
}
#override
void initState() {
// TODO: implement initState
super.initState();
_IsSearching = false;
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: buildBar(context),
body: new Container(
color: Colors.transparent,
child: ListView.builder(
itemCount: allblogs.length,
// Facing Issue Here
itemBuilder: _IsSearching ? buildSearchList : blogslist
),
),
);
}
// Facing Issue Here
Widget buildSearchList(BuildContext context, int index){
if (_searchText.isEmpty){
return blogslist(context, index);
}
else {
List<String> _searchList = List();
for (int i = 0; i < allblogs.length; i++) {
String name = (allblogs[index].blogName);
if (name.toLowerCase().contains(_searchText.toLowerCase())) {
_searchList.add(name);
}
}
// Now what can i return to show the tile whoes blogName I searched for
);
}
}
Widget buildBar(BuildContext context) {
return AppBar(
centerTitle: true,
title: appBarTitle,
backgroundColor: widget._tabBackgroudColor,
actions: <Widget>[
IconButton(icon: actionIcon,
onPressed: () {
setState(() {
if (this.actionIcon.icon == Icons.search) {
// ignore: new_with_non_type
this.actionIcon = new Icon(Icons.close, color: Colors.white,);
this.appBarTitle = TextField(
controller: _searchQuery,
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
prefixIcon: new Icon(Icons.search, color: Colors.white),
hintText: "Search...",
hintStyle: TextStyle(color: Colors.white)
),
);
_handleSearchStart();
}
else {
_handleSearchEnd();
}
});
},),
],
);
}
void _handleSearchStart() {
setState(() {
_IsSearching = true;
});
}
void _handleSearchEnd() {
setState(() {
// ignore: new_with_non_type
this.actionIcon = new Icon(Icons.search, color: Colors.white,);
this.appBarTitle = new Text("Search Sample", style: TextStyle(
color: Colors.white,
),);
_IsSearching = false;
_searchQuery.clear();
});
}
}
Widget blogslist(BuildContext context, int index){
return Container(
padding: const EdgeInsets.only(top: 5.0),
child: Column(
children: <Widget>[
ListTile(
leading: Padding(
padding: const EdgeInsets.all(3.0),
child: new Image(image: AssetImage("assets/images/icons/stackexchange.png")),
),
title: Text(allblogs[index].blogName,
),
subtitle: Text(allblogs[index].blogName),
contentPadding: EdgeInsets.symmetric(horizontal: 3.0),
isThreeLine: true,
trailing: Padding(padding: const EdgeInsets.only(left: 5.0),
child: IconButton(icon: Icon(Icons.launch, color: Colors.blue, size: 20.0,),
onPressed: (){}),
),
),
Divider(),
],
),
);
}
All I want is to search the ListTile widget in the flutter based on the title
You can also see the image which I uploaded that shows I achieved the situation in which I can type something in the search bar. Now I just need to compare the input text with the ListTile's title, and show the matched tiles.
I have created a list in different class like----
class AllBlogs {
final String id;
final String blogName;
final String blogurl;
final String about;
const AllBlogs(
{#required this.id,
#required this.blogName,
#required this.blogurl,
#required this.about});
}
List<AllBlogs> allblogs = [
const AllBlogs(
id: '1',
blogName: 'KDnuggets',
blogurl: "https://www.kdnuggets.com/?ref=cybrhome",
about: "KDnuggets is one of the most popular data science blogs, with articles that cover Business Analytics, Statistics, and Machine Learning.",
),
and when I am trying to write below code then at place of allblogs.It's showing an error of 'a value of type List can't be assigned to a variable of type List class.
You have a List<Blog> somewhere called allblogs. Each time the search text changes form a new sublist as follows:
List<Blog> sublist = allblogs.where((b) => b.name.toLowerCase().contains(_searchText.toLowerCase())).toList();
(if search text is empty then simply assign allblogs to sublist)
Now use sublist everywhere you currently use allblogs in your builds.
So, on every change to the search criterion, you filter the full list down to the sub list that matches and (as long as you do that in setState) the Widget tree redraws showing just the filtered list.
Here's a complete working example based on your snippet above:
import 'package:flutter/material.dart';
main() {
runApp(new MaterialApp(
title: 'Blogs Test',
home: new AllBlogs(),
));
}
class Blog {
String blogName;
Blog(this.blogName);
}
List<Blog> allblogs = [
Blog('flutter'),
Blog('dart'),
Blog('java'),
Blog('python'),
];
class AllBlogs extends StatefulWidget {
AllBlogs({Key key}) : super(key: key);
final Color _tabBackgroundColor = const Color(0xFF1A237E);
#override
AllBlogsState createState() => AllBlogsState();
}
class AllBlogsState extends State<AllBlogs> {
Widget appBarTitle = Text("Blog's List");
Icon actionIcon = Icon(
Icons.search,
color: Colors.white,
);
final key = new GlobalKey<ScaffoldState>();
final TextEditingController _searchQuery = new TextEditingController();
List<Blog> _displayList = allblogs;
#override
void initState() {
super.initState();
_searchQuery.addListener(() {
if (_searchQuery.text.isEmpty) {
setState(() {
_displayList = allblogs;
});
} else {
setState(() {
String s = _searchQuery.text;
_displayList = allblogs
.where((b) => b.blogName.toLowerCase().contains(s.toLowerCase()))
.toList();
});
}
});
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: buildBar(context),
body: new Container(
color: Colors.transparent,
child: ListView.builder(
itemCount: _displayList.length,
itemBuilder: _blogBuilder,
),
),
);
}
Widget _blogBuilder(BuildContext context, int index) {
return Container(
padding: const EdgeInsets.only(top: 5.0),
child: Column(
children: <Widget>[
ListTile(
leading: Padding(
padding: const EdgeInsets.all(3.0),
child: new Image(
image: AssetImage("assets/images/icons/stackexchange.png")),
),
title: Text(_displayList[index].blogName),
subtitle: Text(_displayList[index].blogName),
contentPadding: EdgeInsets.symmetric(horizontal: 3.0),
isThreeLine: true,
trailing: Padding(
padding: const EdgeInsets.only(left: 5.0),
child: IconButton(
icon: Icon(
Icons.launch,
color: Colors.blue,
size: 20.0,
),
onPressed: () {}),
),
),
Divider(),
],
),
);
}
Widget buildBar(BuildContext context) {
return AppBar(
centerTitle: true,
title: appBarTitle,
backgroundColor: widget._tabBackgroundColor,
actions: <Widget>[
IconButton(
icon: actionIcon,
onPressed: () {
setState(() {
if (this.actionIcon.icon == Icons.search) {
this.actionIcon = new Icon(
Icons.close,
color: Colors.white,
);
this.appBarTitle = TextField(
controller: _searchQuery,
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
prefixIcon: new Icon(Icons.search, color: Colors.white),
hintText: "Search...",
hintStyle: TextStyle(color: Colors.white)),
);
} else {
this.actionIcon = new Icon(
Icons.search,
color: Colors.white,
);
this.appBarTitle = new Text(
"Search Sample",
style: TextStyle(
color: Colors.white,
),
);
_searchQuery.clear();
}
});
},
),
],
);
}
}