Comments (11)
Hi @phranklins ,
Thanks for raising this issue.
I tried again the code example in #103 which seems to be the closest I could get to your situation and I got no issue running with latest version of the plugin.
Could it be that the error occurs because your data is different?
If I had to guess, I would suspect that your items are indexed with integers and not strings. In data terms, they are a list while the example code expects a map. However, without the code, it is hard to confirm.
Do you have some code you could share so that I can try to investigate further?
from search_choices.
I'm actually pretty much using your example code as is so it's weird that I'm running into issues while you aren't. The biggest differences between your code and mine are:
- I removed the filter and sorting options since I don't need them
- added a proxy to your example URL to make it work in web
- I removed the web conditions since with the proxy, it should work in web
- I had to replace
value: item,
withvalue: item["capital"],
. If I didn't I would receive, the message Error: Expected a value of type 'String', but got one of type '_JsonMap'. That seems expected since you mention it should be a map, but if I left it that way, I always got the error and the only way past it was to change value the way that I did - I replaced selectedValueWidgetFn with the code in #103 , but I would receive the error Expected a value of type 'int', but got one of type 'String' regardless of whether I used this code or the code in the example.
Here is basically the code I have for the widget:
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:search_choices/search_choices.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:http/http.dart';
class SearchCapitals extends StatefulWidget {
const SearchCapitals({
Key? key,
this.width,
this.height,
}) : super(key: key);
final double? width;
final double? height;
@override
_SearchCapitalsState createState() => _SearchCapitalsState();
}
class _SearchCapitalsState extends State<SearchCapitals> {
@override
String? selectedValueSingleDialogPagedFuture;
PointerThisPlease<int> currentPage = PointerThisPlease<int>(1);
Widget build(BuildContext context) {
return SearchChoices.single(
icon: const Icon(Icons.keyboard_arrow_down_rounded),
displayClearIcon: false,
padding: 4,
value: selectedValueSingleDialogPagedFuture,
hint: Text(
"Search capitals",
style: TextStyle(
color: black,
fontWeight: FontWeight.w300),
),
searchHint: Text(
"Search capitals",
style: TextStyle(fontWeight: FontWeight.bold),
),
underline: Container(
height: 0,
),
onChanged: (value) {
setState(() {
selectedValueSingleDialogPagedFuture = value;
});
},
isExpanded: true,
itemsPerPage: 15,
currentPage: currentPage,
selectedValueWidgetFn: (item) {
return DropdownMenuItem(child: (Text(item["capital"])));
},
displayItem: (item, selected) {
return (Row(children: [
selected
? Icon(
Icons.radio_button_checked,
color: Colors.grey,
)
: Icon(
Icons.radio_button_unchecked,
color: Colors.grey,
),
SizedBox(width: 7),
Expanded(
child: item,
),
]));
},
futureSearchFn: (String? keyword, String? orderBy, bool? orderAsc,
List<Tuple2<String, String>>? filters, int? pageNb) async {
String filtersString = "";
int i = 1;
filters?.forEach((element) {
filtersString += "&filter" +
i.toString() +
"=" +
element.item1 +
"," +
element.item2;
i++;
});
Response response = await get(Uri.parse(
"https://corsproxy.io/?https://searchchoices.jod.li/exampleList.php?page=${pageNb ?? 1},10${orderBy == null ? "" : "&order=" + orderBy + "," + (orderAsc ?? true ? "asc" : "desc")}${(keyword == null || keyword.isEmpty) ? "" : "&filter=capital,cs," + keyword}$filtersString"))
.timeout(Duration(
seconds: 10,
));
if (response.statusCode != 200) {
throw Exception("failed to get data from internet");
}
dynamic data = jsonDecode(response.body);
int nbResults = data["results"];
List<DropdownMenuItem> results = (data["records"] as List)
.map<DropdownMenuItem>((item) => DropdownMenuItem(
value: item["capital"],
child:
Text("${item["capital"]} - ${item["country"]} - ${item["continent"]} - pop.: ${item["population"]}"),
))
.toList();
return (Tuple2<List<DropdownMenuItem>, int>(results, nbResults));
},
searchDelay: 500,
futureSearchRetryButton: (Function onPressed) => Column(children: [
SizedBox(height: 15),
Center(
child: ElevatedButton.icon(
onPressed: () {
onPressed();
},
icon: Icon(Icons.refresh),
label: Text("Enter at least 3 characters\n or click to retry")),
)
]),
);
}
}
from search_choices.
Thanks for the additional details!
I cannot run your example right now.
Do you have a specific line/character pointed at with the "got a String while expecting an int" error?
If you run in debug mode with a breakpoint on this line, does the data look as expected?
from search_choices.
Yeah the data looks as expected, but for some reason I feel the search choices code is what's blocking it. I wish the post had line numbers. Basically I've experienced two errors:
- For code line 98, I receive the error Error: Expected a value of type 'String', but got one of type '_JsonMap' if the line is
value: item,
. I was able to get passed the error by changing the line tovalue: item["capital"],
As you mentioned, I ideally do want a map and when I look at the data, I see a map. But the error is saying it wants a string, which is why I changed it. - For lines 53-55 for selectedValueWidgetFn, I receive the error Expected a value of type 'int', but got one of type 'String'. Not sure why it's expecting an int since I haven't specified it as such. If I delete these lines, the code works just fine except that the styling doesn't match the other dropdowns in the app.
from search_choices.
Your code turns the item
as in the value: item["capital"],
part into a String. It is already the capital.
So, running this code instead worked for me:
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:search_choices/search_choices.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:http/http.dart';
class SearchCapitals extends StatefulWidget {
const SearchCapitals({
Key? key,
this.width,
this.height,
}) : super(key: key);
final double? width;
final double? height;
@override
_SearchCapitalsState createState() => _SearchCapitalsState();
}
class _SearchCapitalsState extends State<SearchCapitals> {
@override
String? selectedValueSingleDialogPagedFuture;
PointerThisPlease<int> currentPage = PointerThisPlease<int>(1);
Widget build(BuildContext context) {
return SearchChoices.single(
icon: const Icon(Icons.keyboard_arrow_down_rounded),
displayClearIcon: false,
padding: 4,
value: selectedValueSingleDialogPagedFuture,
hint: Text(
"Search capitals",
style: TextStyle(
color: black,
fontWeight: FontWeight.w300),
),
searchHint: Text(
"Search capitals",
style: TextStyle(fontWeight: FontWeight.bold),
),
underline: Container(
height: 0,
),
onChanged: (value) {
setState(() {
selectedValueSingleDialogPagedFuture = value;
});
},
isExpanded: true,
itemsPerPage: 15,
currentPage: currentPage,
selectedValueWidgetFn: (item) {
return DropdownMenuItem(child: (Text(item)));
},
displayItem: (item, selected) {
return (Row(children: [
selected
? Icon(
Icons.radio_button_checked,
color: Colors.grey,
)
: Icon(
Icons.radio_button_unchecked,
color: Colors.grey,
),
SizedBox(width: 7),
Expanded(
child: item,
),
]));
},
futureSearchFn: (String? keyword, String? orderBy, bool? orderAsc,
List<Tuple2<String, String>>? filters, int? pageNb) async {
String filtersString = "";
int i = 1;
filters?.forEach((element) {
filtersString += "&filter" +
i.toString() +
"=" +
element.item1 +
"," +
element.item2;
i++;
});
Response response = await get(Uri.parse(
"https://corsproxy.io/?https://searchchoices.jod.li/exampleList.php?page=${pageNb ?? 1},10${orderBy == null ? "" : "&order=" + orderBy + "," + (orderAsc ?? true ? "asc" : "desc")}${(keyword == null || keyword.isEmpty) ? "" : "&filter=capital,cs," + keyword}$filtersString"))
.timeout(Duration(
seconds: 10,
));
if (response.statusCode != 200) {
throw Exception("failed to get data from internet");
}
dynamic data = jsonDecode(response.body);
int nbResults = data["results"];
List<DropdownMenuItem> results = (data["records"] as List)
.map<DropdownMenuItem>((item) => DropdownMenuItem(
value: item["capital"],
child:
Text("${item["capital"]} - ${item["country"]} - ${item["continent"]} - pop.: ${item["population"]}"),
))
.toList();
return (Tuple2<List<DropdownMenuItem>, int>(results, nbResults));
},
searchDelay: 500,
futureSearchRetryButton: (Function onPressed) => Column(children: [
SizedBox(height: 15),
Center(
child: ElevatedButton.icon(
onPressed: () {
onPressed();
},
icon: Icon(Icons.refresh),
label: Text("Enter at least 3 characters\n or click to retry")),
)
]),
);
}
}
If you wish to keep the item as a full result from the json, you will need to keep the value set as item instead of item["capital"] as follows:
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:search_choices/search_choices.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:http/http.dart';
class SearchCapitals extends StatefulWidget {
const SearchCapitals({
Key? key,
this.width,
this.height,
}) : super(key: key);
final double? width;
final double? height;
@override
_SearchCapitalsState createState() => _SearchCapitalsState();
}
class _SearchCapitalsState extends State<SearchCapitals> {
@override
String? selectedValueSingleDialogPagedFuture;
PointerThisPlease<int> currentPage = PointerThisPlease<int>(1);
Widget build(BuildContext context) {
return SearchChoices.single(
icon: const Icon(Icons.keyboard_arrow_down_rounded),
displayClearIcon: false,
padding: 4,
value: selectedValueSingleDialogPagedFuture,
hint: Text(
"Search capitals",
style: TextStyle(
color: black,
fontWeight: FontWeight.w300),
),
searchHint: Text(
"Search capitals",
style: TextStyle(fontWeight: FontWeight.bold),
),
underline: Container(
height: 0,
),
onChanged: (value) {
setState(() {
selectedValueSingleDialogPagedFuture = value;
});
},
isExpanded: true,
itemsPerPage: 15,
currentPage: currentPage,
selectedValueWidgetFn: (item) {
return DropdownMenuItem(child: (Text(item["capital"])));
},
displayItem: (item, selected) {
return (Row(children: [
selected
? Icon(
Icons.radio_button_checked,
color: Colors.grey,
)
: Icon(
Icons.radio_button_unchecked,
color: Colors.grey,
),
SizedBox(width: 7),
Expanded(
child: item,
),
]));
},
futureSearchFn: (String? keyword, String? orderBy, bool? orderAsc,
List<Tuple2<String, String>>? filters, int? pageNb) async {
String filtersString = "";
int i = 1;
filters?.forEach((element) {
filtersString += "&filter" +
i.toString() +
"=" +
element.item1 +
"," +
element.item2;
i++;
});
Response response = await get(Uri.parse(
"https://corsproxy.io/?https://searchchoices.jod.li/exampleList.php?page=${pageNb ?? 1},10${orderBy == null ? "" : "&order=" + orderBy + "," + (orderAsc ?? true ? "asc" : "desc")}${(keyword == null || keyword.isEmpty) ? "" : "&filter=capital,cs," + keyword}$filtersString"))
.timeout(Duration(
seconds: 10,
));
if (response.statusCode != 200) {
throw Exception("failed to get data from internet");
}
dynamic data = jsonDecode(response.body);
int nbResults = data["results"];
List<DropdownMenuItem> results = (data["records"] as List)
.map<DropdownMenuItem>((item) => DropdownMenuItem(
value: item,
child:
Text("${item["capital"]} - ${item["country"]} - ${item["continent"]} - pop.: ${item["population"]}"),
))
.toList();
return (Tuple2<List<DropdownMenuItem>, int>(results, nbResults));
},
searchDelay: 500,
futureSearchRetryButton: (Function onPressed) => Column(children: [
SizedBox(height: 15),
Center(
child: ElevatedButton.icon(
onPressed: () {
onPressed();
},
icon: Icon(Icons.refresh),
label: Text("Enter at least 3 characters\n or click to retry")),
)
]),
);
}
}
But I guess there must be a reason why you chose to set the value as item["capital"].
from search_choices.
The reason I set value as item["capital"] is what I mention in point 1 of my previous comment. If I set it to just value: item
like you did, I get an error that says Expected a value of type 'String', but got one of type '_JsonMap'
from search_choices.
Oh, indeed, you explained that. Sorry, I didn't pay enough attention.
Yet, I don't see why you get this issue for now.
Is it fine for you to run with the first solution mentioned in my previous comment?
from search_choices.
Yep. Appreciate that. Just tried that and it did work. So for now, will make do with this for now. Thank you!
from search_choices.
Great, thanks!
I hope you don't mind if I close this issue for now.
Don't hesitate to reopen if needed.
from search_choices.
FYI, I figured out why I was getting that first error with string vs. jsonmap. It was a stupid mistake. You can see above that I have the String? selectedValueSingleDialogPagedFuture;
which should be dynamic? selectedValueSingleDialogPagedFuture;
. I was using selectedValueSingleDialog elsewhere in my code and only replaced the latter half of the this line instead of the updating the whole thing.... Given that, updated the code to reflect that mistake and everything is working as it should.
from search_choices.
Thank you very much for the explanation @phranklins . I'm glad it is working now fine for you!
from search_choices.
Related Issues (20)
- futureSearchFn delays requests instead of debounce them HOT 9
- build failed after flutter upgrade HOT 9
- Customize future search order and filter icons HOT 10
- [FEATURE REQUEST] - Wrap items of SearchChoices.multiple() widget HOT 11
- When using futureSearchFn type 'String' is not a subtype of type 'DropdownMenuItem<String>' HOT 2
- searchFn seems to have issues with custom classes in release mode HOT 5
- searchFn works on iPhone Simulator, but not iPhone (14 Pro Max) HOT 8
- [Improves] New style HOT 7
- Android fails with gradle 8 HOT 2
- Selected value in SearchChoice.single not working in Mobile but works fine in Web HOT 5
- RTL support - dropdown button has to be on the left side when RTL locale selected in app HOT 7
- Remove the margin/padding in sides & redesign options buttons HOT 7
- Problems for install search_choices version 2.2.7
- Update value from outside the plugin doesn't work
- How delete value selected from a buttom
- Duplicate class kotlin.collections.jdk8.CollectionsJDK8Kt found HOT 1
- futureSearchFn does not work with Custom Object HOT 6
- Clear button is always disabled HOT 3
- Upgrade to latest gradle version
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from search_choices.