Home > Enterprise >  Converting QueryDocumentSnapshot to model type causes exception
Converting QueryDocumentSnapshot to model type causes exception

Time:10-09

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())),),);

  • Related