Skip to content

Instantly share code, notes, and snippets.

@edoardoc
Last active April 9, 2021 07:38
Embed
What would you like to do?
my take at the standard flutter autocomplete while unmarshaling a json with a custom type
import 'dart:convert';
import 'package:flutter/material.dart';
class RawAutocompleteEddy extends StatelessWidget {
const RawAutocompleteEddy({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('my take at RawAutocomplete \nCustomType unmarshal'),
),
body: const Center(
child: AutocompleteCustomTypeExample(),
),
),
);
}
}
/*
{
"match": "Badia Polesine",
"tipo": "comune",
"idprovincia": 29,
"provincia": "Rovigo",
"idcomune": 2770,
"comune": "Badia Polesine",
"zonaid": null,
"zona": null
},
*/
// An example of a type that someone might want to autocomplete a list of.
@immutable
class Posto {
const Posto({
required this.match,
required this.tipo,
required this.idprovincia,
required this.provincia,
required this.idcomune,
required this.comune,
required this.zonaid,
});
final String match;
final String tipo;
final int idprovincia;
final String provincia;
final int idcomune;
final String comune;
final int zonaid;
factory Posto.fromJson(Map<String, dynamic> json) {
return Posto(
match: json['match'] ?? "",
tipo: json['tipo'] ?? "",
idprovincia: json['idprovincia'] ?? 0,
provincia: json['provincia'] ?? "",
idcomune: json['idcomune'] ?? 0,
comune: json['comune'] ?? "",
zonaid: json['zonaid'] ?? 0,
);
}
@override
String toString() {
return '$match, $tipo';
}
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType) {
return false;
}
return other is Posto && other.match == match && other.tipo == tipo;
}
@override
int get hashCode => hashValues(tipo, match);
}
class AutocompleteCustomTypeExample extends StatelessWidget {
const AutocompleteCustomTypeExample({Key? key}) : super(key: key);
static const String dati =
'[{"match":"Centocelle","tipo":"zona","idprovincia":58,"provincia":"Roma","idcomune":6915,"comune":"Roma","zonaid":141,"zona":"Centocelle"},{"match":"Centro Direzionale Centocelle","tipo":"zona","idprovincia":58,"provincia":"Roma","idcomune":6915,"comune":"Roma","zonaid":144,"zona":"Centro Direzionale Centocelle"}]';
static List<Posto> _userOptions = <Posto>[];
static String _displayStringForOption(Posto option) => option.match;
@override
Widget build(BuildContext context) {
return RawAutocomplete<Posto>(
optionsBuilder: (TextEditingValue textEditingValue) {
debugPrint("azione ${textEditingValue.text.toLowerCase()}"); // TODO: this would be a good time to query new data
final parsed = json.decode(dati).cast<Map<String, dynamic>>();
_userOptions = parsed.map<Posto>((json) => Posto.fromJson(json)).toList();
return _userOptions.where((Posto option) {
// Search based on Posto.toString, which includes both match and
// tipo, even though the display string is just the match.
return option.toString().contains(textEditingValue.text.toLowerCase());
});
},
displayStringForOption: _displayStringForOption,
fieldViewBuilder: (BuildContext context, TextEditingController textEditingController, FocusNode focusNode, VoidCallback onFieldSubmitted) {
return TextFormField(
controller: textEditingController,
focusNode: focusNode,
onFieldSubmitted: (String value) {
onFieldSubmitted();
},
);
},
optionsViewBuilder: (BuildContext context, AutocompleteOnSelected<Posto> onSelected, Iterable<Posto> options) {
return Align(
alignment: Alignment.topLeft,
child: Material(
elevation: 4.0,
child: SizedBox(
height: 200.0,
child: ListView.builder(
padding: const EdgeInsets.all(8.0),
itemCount: options.length,
itemBuilder: (BuildContext context, int index) {
final Posto option = options.elementAt(index);
return GestureDetector(
onTap: () {
onSelected(option);
},
child: ListTile(
title: Text(_displayStringForOption(option)),
),
);
},
),
),
),
);
},
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment