'Flutter: Dart Error: RangeError (index): Invalid value: Only valid value is 0: 1
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
Solution 1:[1]
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.
Solution 2:[2]
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.
Solution 3:[3]
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
- you can check line code has "if" ...
- check length of list > 0
- "var _size = _res[index];" maybe index null
Solution 4:[4]
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Kaushik Chandru |
Solution 3 | Otis |
Solution 4 | Mohammed Fouad |