I am populating a ListView.builder with a Firestore query and then I can filter the items using a TextField controller,
This is the code just until the ListView.builder widget:
class ListaUsuarios extends StatefulWidget {
const ListaUsuarios({Key key}) : super(key: key);
@override
_ListaUsuariosState createState() => _ListaUsuariosState();
}
class _ListaUsuariosState extends State<ListaUsuarios> {
TextEditingController _controller = new TextEditingController();
List _allResults = [];
List _usuariosFiltrados = [];
Future resultsLoaded;
@override
void initState() {
// TODO: implement initState
super.initState();
_controller.addListener(_onSearchChanged);
}
void didChangeDependencies(){
super.didChangeDependencies();
resultsLoaded = getUsuariosSnapShot();
}
getUsuariosSnapShot() async {
var data = await FirebaseFirestore.instance
.collection("users")
.orderBy("username")
.get();
setState(() {
_allResults = data.docs;
});
searchResultsList();
return "complete";
}
void _onSearchChanged() {
searchResultsList();
print(_controller.text);
}
searchResultsList(){
var showResults = [];
if(_controller.text != ""){
//tenemos parametro de busqueda
var busqueda = _controller.text.toLowerCase();
for (var usuarioSnaphot in _allResults) {
var username = Usuario
.fromSnapshot(usuarioSnaphot).username.toLowerCase();
var about = Usuario
.fromSnapshot(usuarioSnaphot).about.toLowerCase();
var city = Usuario
.fromSnapshot(usuarioSnaphot).city.toLowerCase();
var country = Usuario
.fromSnapshot(usuarioSnaphot).country.toLowerCase();
var email = Usuario
.fromSnapshot(usuarioSnaphot).email.toLowerCase();
var first_name = Usuario
.fromSnapshot(usuarioSnaphot).first_name.toLowerCase();
var last_name = Usuario
.fromSnapshot(usuarioSnaphot).last_name.toLowerCase();
var web = Usuario
.fromSnapshot(usuarioSnaphot).web.toLowerCase();
if (username.contains(busqueda) || about.contains(busqueda) || city.contains(busqueda) || country.contains(busqueda) || email.contains(busqueda) || first_name.contains(busqueda) || last_name.contains(busqueda) || web.contains(busqueda)){
showResults.add(usuarioSnaphot);
}
}
}
else{
showResults = List.from(_allResults);
}
setState(() {
_usuariosFiltrados = showResults;
});
}
@override
Widget build(BuildContext context) {
print("estoy en lista de uusarioas");
return Scaffold(
appBar: AppBar(
backgroundColor: AppColors.rojoMovMap,
title: Text("Usuarios Mov-Map")
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("La búsqueda actual se ejecuta buscando en los campos: about, city, country, email, first_name, last_name y web",style: TextStyle(fontSize: 14,color: Colors.black38, fontStyle: FontStyle.italic),),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text("Si quieres buscar por otros tipos",style: TextStyle(fontSize: 14,color: Colors.black38, fontStyle: FontStyle.italic),),
Spacer(),
RaisedButton(
child: Text('Otras búsquedas \nde usuarios',style: TextStyle(color: Colors.white,fontSize: 13),),
color: Colors.red,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(16.0))),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ListaUsuarios()),
);
},
)
],
),
),
TextField(
controller: _controller,
decoration: InputDecoration(
prefixIcon: Icon(Icons.search),
),
),
Expanded(
child: ListView.builder(
itemCount: _usuariosFiltrados.length,
itemBuilder: (BuildContext context, int index){
Here you have the declaration of Usuario.fromSnapshot:
Usuario.fromSnapshot(DocumentSnapshot snapshot)
: about = snapshot['about'],
city = snapshot['city'],
country = snapshot['country'],
email = snapshot['email'],
email_verified = snapshot['email_verified'],
first_name = snapshot['first_name'],
is_active = snapshot['is_active'],
is_ambassador = snapshot['is_ambassador'],
is_business = snapshot['is_business'],
is_movmap_admin = snapshot['is_movmap_admin'],
last_name = snapshot['last_name'],
profile_background = snapshot['profile_background'],
profile_image = snapshot['profile_image'],
sex = snapshot['sex'],
tel = snapshot['tel'],
tel_verified = snapshot['tel_verified'],
token_firebase = snapshot['token_firebase'],
userId = snapshot['userId'],
username = snapshot['username'],
web = snapshot['web'];
Everything is working fine, I am getting the Firestore Documents snapshots and showing them on the listview, but now I would need to select one of the items and show their data values in a detail page/screen in order to edit some of then if needed.
My issue is that I am trying to pass the item values to the detail page/screen as follows:
RaisedButton(
child: Text('Editar este usuario',style: TextStyle(color: Colors.white,fontSize: 20),),
color: Colors.red,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(16.0))),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => EditarUsuario(usuario: _usuariosFiltrados[index]),),
);
},
)
The page/class EditarUsuario needs a var of type Usuario to edit the values, but when clicking the button to navigate to the detail page an exception is shown:
flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
flutter: The following _TypeError was thrown building Builder(dirty):
flutter: type 'QueryDocumentSnapshot' is not a subtype of type 'Usuario'
flutter:
CodePudding user response:
Use a factory that return Usuario from _usuariosFiltrados[index].data().
class Usuario {
final String about;
final String country;
final String email;
final bool email_verified;
final String first_name;
final bool is_active;
final bool is_ambassador;
final bool is_business;
final bool is_movmap_admin;
final String last_name;
final String profile_background;
final String profile_image;
final String sex;
final String tel;
final bool tel_verified;
final String token_firebase;
final String userId;
final String username;
final String web;
Usuario(
{required this.about,
required this.country,
required this.email,
required this.email_verified,
required this.first_name,
required this.is_active,
required this.is_ambassador,
required this.is_business,
required this.is_movmap_admin,
required this.last_name,
required this.profile_background,
required this.profile_image,
required this.sex,
required this.tel,
required this.tel_verified,
required this.token_firebase,
required this.userId,
required this.username,
required this.web});
Map<String, dynamic> toMap() {
return {
'about': about,
'country': country,
'email': email,
'email_verified': email_verified,
'first_name': first_name,
'is_active': is_active,
'is_ambassador': is_ambassador,
'is_business': is_business,
'is_movmap_admin': is_movmap_admin,
'last_name': last_name,
'profile_background': profile_background,
'profile_image': profile_image,
'sex': sex,
'tel': tel,
'tel_verified': tel_verified,
'token_firebase': token_firebase,
'userId': userId,
'username': username,
'web': web,
};
}
factory Usuario.fromMap(Map<String, dynamic> map) {
return Usuario(
about: map['about'] as String,
country: map['country'] as String,
email: map['email'] as String,
email_verified: map['email_verified'] as bool,
first_name: map['first_name'] as String,
is_active: map['is_active'] as bool,
is_ambassador: map['is_ambassador'] as bool,
is_business: map['is_business'] as bool,
is_movmap_admin: map['is_movmap_admin'] as bool,
last_name: map['last_name'] as String,
profile_background: map['profile_background'] as String,
profile_image: map['profile_image'] as String,
sex: map['sex'] as String,
tel: map['tel'] as String,
tel_verified: map['tel_verified'] as bool,
token_firebase: map['token_firebase'] as String,
userId: map['userId'] as String,
username: map['username'] as String,
web: map['web'] as String,
);
}
}
then
Navigator.push(context,MaterialPageRoute(
builder:(context)=>EditarUsuario(usuario: Usuario.fromMap(_usuariosFiltrados[index].data())),),);