Reputation: 327
Hey guys I am new to Flutter and trying to build a variation selector for an eCommerce application. I am getting this error while trying to build a size variation widget for the size-color
variation. It works for size
only or color
only variation. This is the error RangeError (index): Invalid value: Only valid value is 0: 1
.
Also, when I print the length of the array, I am getting the value 1.
The idea is to show the available sizes when someone clicks on a color that gets displayed without any issues. but while trying to show the size, facing this error.
This is the code
///size widget
class SelectSizeWidget extends StatefulWidget {
SelectSizeWidget({
Key? key,
}) : super(key: key);
@override
_SelectSizeWidgetState createState() => _SelectSizeWidgetState();
}
class _SelectSizeWidgetState extends State<SelectSizeWidget> {
@override
Widget build(BuildContext context) {
return Consumer<ProductController>(
builder: (_,model,__) {
return Wrap(
spacing: 8,
runSpacing: 8,
children: List.generate((model.sizeColour.isNotEmpty) ? model.ss.length : model.size.length , (index) {
if(model.sizeColour.isNotEmpty) {
if(model.selectedColour != null || model.selectedColour != ""){
var _res = model.sizeColour
.where((element) =>
element.var2!.toUpperCase() == model.selectedColour)
.toList();
var _size = _res[index];
return buildSize(_size);
} else {
var _res = model.sizeColour.toList();
var _size = _res[index];
return buildSize(_size);
}
} else if (model.size.isNotEmpty) {
var _size = model.size[index];
return buildSize(_size);
}else if(model.materialSize.isNotEmpty){
var _res = model.materialSize.where((element) =>
element.var1.toUpperCase() == model.selectedMaterial)
.toList();
var _size = _res[index];
return buildSize(_size);
}else{
return SizedBox.shrink();
}
}),
);
}
);
}
SizedBox buildSize(Variant size) {
return SizedBox(
height: 38,
child: RawChip(
label: Text(size.var1),
labelStyle: TextStyle(color: Theme.of(context).hintColor),
padding: EdgeInsets.symmetric(horizontal: 7, vertical: 7),
backgroundColor: Theme.of(context).focusColor.withOpacity(0.05),
selectedColor: Theme.of(context).focusColor.withOpacity(0.2),
selected: size.varId == context.read<ProductController>().selectedVariation,
shape: StadiumBorder(side: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.05))),
onSelected: (bool value) {
context.read<ProductController>().setSize(size.varId);
},
),
);
}
}
Productcontroller - for detail
List<Variant> size = [];
List<Variant> colour = [];
List<Variant> sizeColour = [];
List<String> ss = [];
List<String> cc = [];
Future<bool> getProductDetails({required String slug}) async {
final val = await ApiProvider().getProductDetails(slug: slug);
if (val.statusCode == 200 || val.statusCode == 201) {
product = productDetailsResponseFromJson(jsonEncode(val.data));
/// variation
if (product!.variants) {
clearAll();
List<Map<int, Set<String>>> sc = [];
List<String> s = [];
List<String> c = [];
selectedVariation = product!.prdtVari.first.id;
for (var each in product!.prdtVari) {
var _var = each.variation.toLowerCase();
if (_var == 'colour') {
colour.add(Variant(
varId: each.id,
var1: each.variationTypes.first.name,
typeMap1: each.variationTypes.first.typeMap));
c.add(each.variationTypes.first.name);
notifyListeners();
} else if (_var == 'size') {
size.add(Variant(
varId: each.id,
var1: each.variationTypes.first.name,
typeMap1: each.variationTypes.first.typeMap));
s.add(each.variationTypes.first.name);
notifyListeners();
} else if (_var == 'size-colour') {
sc.add({
each.id: {
each.variationTypes.first.name,
each.variationTypes.last.name
}
});
sizeColour.add(Variant(
varId: each.id,
var1: each.variationTypes.first.name,
typeMap1: each.variationTypes.first.typeMap,
var2: each.variationTypes.last.name,
typeMap2: each.variationTypes.last.typeMap));
s.add(each.variationTypes.first.name);
c.add(each.variationTypes.last.name);
notifyListeners();
}
}
ss = s.toSet().toList();
cc = c.toSet().toList();
if(cc.isNotEmpty){
if(product!.prdtVari.first.variation.toLowerCase() == "colour"){
selectedColour = colour.where((element) => element.varId == selectedVariation!).first.var1.toUpperCase();
} else if(product!.prdtVari.first.variation.toLowerCase() == "size-colour") {
selectedColour = sizeColour.where((element) => element.varId == selectedVariation!).first.var2!.toUpperCase();
}
};
notifyListeners();
}
isLoading = false;
notifyListeners();
return true;
} else {
isLoading = false;
notifyListeners();
return false;
}
}
API model
// To parse this JSON data, do
//
// final productDetailsResponse = productDetailsResponseFromJson(jsonString);
import 'dart:convert';
ProductDetailsResponse productDetailsResponseFromJson(String str) => ProductDetailsResponse.fromJson(json.decode(str));
String productDetailsResponseToJson(ProductDetailsResponse data) => json.encode(data.toJson());
class ProductDetailsResponse {
ProductDetailsResponse({
required this.category,
required this.title,
required this.variants,
required this.slug,
required this.averageReview,
required this.countReview,
required this.productDetailsInfo,
required this.prdtImg,
required this.prdtVari,
});
int category;
String title;
bool variants;
String slug;
double averageReview;
int countReview;
ProductDetailsInfo productDetailsInfo;
List<ProductDetailsImages> prdtImg;
List<ProductDetailsVariation> prdtVari;
factory ProductDetailsResponse.fromJson(Map<String, dynamic> json) => ProductDetailsResponse(
category: json["category"],
title: json["title"],
variants: json["var"],
slug: json["slug"],
averageReview: json["rating"],
countReview: json["rCount"],
productDetailsInfo: ProductDetailsInfo.fromJson(json["prdtInfo"]),
prdtImg: List<ProductDetailsImages>.from(json["prdtImg"].map((x) => ProductDetailsImages.fromJson(x))),
prdtVari: List<ProductDetailsVariation>.from(json["prdtVari"].map((x) => ProductDetailsVariation.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"category": category,
"title": title,
"var": variants,
"slug": slug,
"rating": averageReview,
"rCount": countReview,
"prdtInfo": productDetailsInfo.toJson(),
"prdtImg": List<dynamic>.from(prdtImg.map((x) => x.toJson())),
"prdtVari": List<dynamic>.from(prdtVari.map((x) => x.toJson())),
};
}
class ProductDetailsImages {
ProductDetailsImages({
required this.id,
required this.images,
required this.cover,
});
int id;
String? images;
bool cover;
factory ProductDetailsImages.fromJson(Map<String, dynamic> json) => ProductDetailsImages(
id: json["id"],
images: json["images"],
cover: json["cover"],
);
Map<String, dynamic> toJson() => {
"id": id,
"images": images,
"cover": cover,
};
}
class ProductDetailsInfo {
ProductDetailsInfo({
required this.brand,
required this.mrp,
required this.price,
required this.inStock,
required this.desc,
required this.shipCost,
required this.condition,
});
String? brand;
double mrp;
double price;
String inStock;
String desc;
double? shipCost;
String condition;
factory ProductDetailsInfo.fromJson(Map<String, dynamic> json) => ProductDetailsInfo(
brand: json["brd"],
mrp: json["mrp"],
price: json["price"],
inStock: json["iStock"],
desc: json["desc"],
shipCost: json["shCost"],
condition: json["con"],
);
Map<String, dynamic> toJson() => {
"brand": brand,
"mrp": mrp,
"price": price,
"iStock": inStock,
"desc": desc,
"shCost": shipCost,
"con": condition,
};
}
class ProductDetailsVariation {
ProductDetailsVariation({
required this.id,
required this.variation,
required this.mrp,
required this.price,
required this.inStock,
required this.images,
required this.variationTypes,
});
int id;
String variation;
double mrp;
double price;
String inStock;
List<ProductDetailsImages> images;
List<ProductDetailsVariationType> variationTypes;
factory ProductDetailsVariation.fromJson(Map<String, dynamic> json) => ProductDetailsVariation(
id: json["id"],
variation: json["vAtion"],
mrp: json["mrp"],
price: json["price"],
inStock: json["iStock"],
images: List<ProductDetailsImages>.from(json["imgs"].map((x) => ProductDetailsImages.fromJson(x))),
variationTypes: List<ProductDetailsVariationType>.from(json["vTypes"].map((x) => ProductDetailsVariationType.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"id": id,
"vAtion": variation,
"mrp": mrp,
"price": price,
"iStock": inStock,
"imgs": List<dynamic>.from(images.map((x) => x.toJson())),
"vTypes": List<dynamic>.from(variationTypes.map((x) => x.toJson())),
};
}
class ProductDetailsVariationType {
ProductDetailsVariationType({
required this.id,
required this.name,
required this.typeMap,
});
int id;
String name;
String typeMap;
factory ProductDetailsVariationType.fromJson(Map<String, dynamic> json) => ProductDetailsVariationType(
id: json["id"],
name: json["name"],
typeMap: json["tMap"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"tMap": typeMap,
};
}
Thanks
Upvotes: 0
Views: 2039
Reputation: 98
I could not read all the code and test it, but I got that error before. When? for example,
List<String> myList = [1 , 2 ,3 ,4];
child : ListView(
children: [
Text("${mylist[0]}"),
Text("${mylist[1]}"),
Text("${mylist[2]}"),
Text("${mylist[3]}"),
Text("${mylist[4]}"),
]
) ;
so you have four items in the list which mean your index will be just until 3 if you add more than the items in the list it will show that error. I hope I was able to explain.
Upvotes: 0
Reputation: 1157
List.generate
is using model.ss.length
or model.size.length
to generate your list like you instructed on this line
List.generate((model.sizeColour.isNotEmpty) ? model.ss.length : model.size.length , (index) {
It means index <= model.ss.length-1
or index <= model.size.length-1
. Then you did
var _res = model.sizeColour.where((element) => element.var2!.toUpperCase() == model.selectedColour).toList();
So if var _size = _res[index]
throw RangeError
it means _res.length < model.ss.length-1
or _res.length < model.size.length-1
but it should be equal, so the solution is to make sure the 3 arrays have the same length.
Upvotes: 1
Reputation: 196
Error often happen when you render data in list but you hasn't data you try check null in code because you not have controller call api or data any where
Upvotes: 0
Reputation: 17772
Try replacing the 'or' with 'and'
if(model.selectedColour != null && model.selectedColour != "")
Since you used or it is always true if either of the condition is met. So even it's empty that variable was assigned with empty value.
Upvotes: 0