Home > Software design >  Firebase Search Field with a Provider as suggestions
Firebase Search Field with a Provider as suggestions

Time:12-26

Hello I am making a chat app in flutter with Firebase where you can search users by their username. I builded a Listview of all the users of my application with a

Provider.of<List<AppUserData>>(context)

for testing and it worked. Now I am trying to use this Stream Provider to provide users by their usernames in a searchbar with the package: searchfield.

enter image description here

Here's my code : search_bar.dart

class SearchBar extends StatefulWidget {
  const SearchBar({Key? key}) : super(key: key);

  @override
  State<SearchBar> createState() => _SearchBarState();
}

class _SearchBarState extends State<SearchBar> {
  static GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  TextEditingController searchController = new TextEditingController();
  @override
  Widget build(BuildContext context) {
    final users = Provider.of<List<AppUserData>>(context);
    return Form(
      key: _formKey,
      child: SearchField(
          suggestions: users
              .map((e) =>
                  SearchFieldListItem(e.toString(), child: Text(e.toString())))
              .toList(),
          controller: searchController,
          searchStyle: const TextStyle(color: dLightGrey),
          searchInputDecoration: const InputDecoration(
            contentPadding: EdgeInsets.fromLTRB(0, 0, 0, 0),
            filled: true,
            fillColor: dDarkGrey,
            prefixIcon: Icon(
              SocketIconv2.ic_search,
              color: dLightGrey,
            ),
            border: OutlineInputBorder(
                borderRadius: BorderRadius.all(Radius.circular(15))),
            hintStyle: TextStyle(
                color: dLightGrey,
                fontFamily: 'SegoeUI',
                fontSize: 18,
                fontWeight: FontWeight.w300),
            hintText: 'Search',
          )),
    );
  }
}

database.dart

class DatabaseService {
  final String? uid;

  DatabaseService({this.uid});
  final CollectionReference userCollection =
      FirebaseFirestore.instance.collection("users");

  Future<void> saveUser(String name, String username) async {
    return await userCollection
        .doc(uid)
        .set({'name': name, 'username': username});
  }

  AppUserData _userFromSnapshot(DocumentSnapshot snapshot) {
    return AppUserData(
        name: snapshot['name'], uid: uid, username: snapshot['username']);
  }

  Stream<AppUserData> get user {
    return userCollection.doc(uid).snapshots().map(_userFromSnapshot);
  }

  List<AppUserData> _userListFromSnapshot(QuerySnapshot snapshot) {
    return snapshot.docs.map((doc) {
      return _userFromSnapshot(doc);
    }).toList();
  }

  Stream<List<AppUserData>> get users {
    return userCollection.snapshots().map(_userListFromSnapshot);
  }

  getUserByUsername(String searchField) async {
    return await userCollection
        .where("username", isGreaterThanOrEqualTo: searchField)
        .get();
  }
}

The parent widget of the search bar :

class _HomePageState extends State<HomePage> {
  final AuthentificationService _auth = AuthentificationService();
  String myName = '';

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final _scaffoldKey = GlobalKey<ScaffoldState>();
    return StreamProvider<List<AppUserData>>.value(
        initialData: [],
        value: DatabaseService().users,
        child: Scaffold(

(Everything else is UI)

And finally here's user.dart:

class AppUser {
  final String? uid;
  AppUser({this.uid});
}

class AppUserData {
  final String? uid;
  final String name;
  final String username;

  AppUserData({this.uid, required this.name, required this.username});
}

With my actual Code I got the Text: "Instance of 'AppUserData' instead of the username I asked for. Thanks in advance for the help :)

CodePudding user response:

You render e.toString() in this code:

child: SearchField(
    suggestions: users
        .map((e) =>
            SearchFieldListItem(e.toString(), child: Text(e.toString())))
        .toList(),

Since you don't override toString in your AppUser class, you get the default implementation, which indeed returns the class name.

If you want to show the user's name, either render e.name or override toString in AppUser to return the string you want.

  • Related