Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to work with Data Model class instead of just Strings? #113

Closed
aytunch opened this issue Jun 24, 2019 · 6 comments
Closed

How to work with Data Model class instead of just Strings? #113

aytunch opened this issue Jun 24, 2019 · 6 comments

Comments

@aytunch
Copy link

aytunch commented Jun 24, 2019

I get a list of Products from my backend and I convert the JSON objects in to a Product Model Class and keep them in a List.

Product class has lets say an id field and a name field.
I can display suggestions with product.name however i get an error when i click on the suggestion. Product is not a subclass of String. How can i get the whole product object when user clicks on a suggestion?

@aytunch
Copy link
Author

aytunch commented Jun 24, 2019

@deakjahn
Copy link

deakjahn commented Jul 9, 2019

suggestionsCallback˛ expects a FutureOr<List<T>>, not a FutureOr<List<String>>. Likewise, onSuggestionSelected passes a T. I have no problems using the package with non-String items.

But I did receive error messages that looked very much like the ones you mention some time ago until I realized that .where(), the filter I used to create my suggestion list, has lazy evaluation and that's not what the widget likes. Isn't this by any chance your problem, too? The solution is easy, just use toList() at the end to evaluate the iterable to a real list. This is a Dart feature, actually, nothing to do with the widget.

@aytunch
Copy link
Author

aytunch commented Jul 18, 2019

@deakjahn Thanks for your input, can you please share a code snippet so I can try and see if it works. I am still having problems:/

@deakjahn
Copy link

deakjahn commented Jul 18, 2019

I have a POCO, very simple:

class Part {
  String name;
  String number;
  List<int> groups;
  List<int> pages;

  Part({this.name, this.number, this.groups, this.pages});
}

When I create the widget, I just use this type:

Widget _buildSearch() => TypeAheadField<Part>(
      itemBuilder: (context, item) => _buildSuggestion(context, item),
      suggestionsCallback: (pattern) async => await _getMatches(pattern),
      onSuggestionSelected: (suggestion) => _showPart(suggestion),
    );

This calls my functions but there is nothing special about them, _buildSuggestion() just returns a Row with the part name and number. The more interesting one will be _getMatches:

Future<List> _getMatches(String query) async {
  if (query.isEmpty)
    return <Part>[];
  else
    return _parts
      .where((item) => item.name.toLowerCase().contains(query.toLowerCase()))
      .take(20)
      .toList();
}

I return a maximum of 20 matching items. And when I return, I don't just return the result of take() but convert it to a list, forcing the otherwise lazy evaluation to actually happen and all list elements to be ready and finished. I think that's what you missed.

@fabiangruss
Copy link

Hi @aytunch ,

I do have the same problem when clicking on a suggestion, which is backed by a custom Model class. Displaying the list of suggestions based on the model is working fine, but clicking on the suggestion always throws the exception "... is not a subtype of type 'String'. Did you solve that issue and if so, how?

Could you post the function behind your onSuggestionSelected @deakjahn ?
That would be a great help. I can't seem to find my error here.

Thank you!

@deakjahn
Copy link

deakjahn commented Jul 22, 2019

I could but you won't find anything interesting there:

void _showPart(Part part) {
  if (part != null)
    // simply use part
    setState(() {
      _name = part.name;
    });
}

Just as you would expect.

If I go in and change the return type of _getMatches() to Future<Iterable> and omit the toList() at the end, I get a similar message but not the same: TakeIterable is not a subtype of type FutureOr<List>. Which is, actually, understandable. But nothing abot Strings. Are you sure you specified your type wherever the generic T is expecting it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants