The main concept is showing documents or fields which contains the searched alphabet.
The search bar gets the given input, it send to the _firebasesearch()
, but in return nothing comes out, and the above image is my database structure, trying to figure out more than a week.
CODE
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_search_bar/flutter_search_bar.dart';
SearchBar searchBar;
GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
class DisplayCourse extends StatefulWidget {
@override
_DisplayCourseState createState() => new _DisplayCourseState();
}
AppBar _buildAppBar(BuildContext context) {
return new AppBar(
title: new Text("FIREBASE QUERY"),
centerTitle: true,
actions: <Widget>[
searchBar.getSearchAction(context),
],
);
}
class _DisplayCourseState extends State<DisplayCourse> {
String _queryText;
_DisplayCourseState() {
searchBar = new SearchBar(
onSubmitted: onSubmitted,
inBar: true,
buildDefaultAppBar: _buildAppBar,
setState: setState,
);
}
void onSubmitted(String value) {
setState(() {
_queryText = value;
_scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text('You have Searched something!'),
backgroundColor: Colors.yellow,
));
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
key: _scaffoldKey,
appBar: searchBar.build(context),
backgroundColor: Colors.red,
body: _fireSearch(_queryText),
);
}
}
Widget _fireSearch(String queryText) {
return new StreamBuilder(
stream: Firestore.instance
.collection('courses')
.where('title', isEqualTo: queryText)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return new Text('Loading...');
return new ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) =>
_buildListItem(snapshot.data.documents[index]),
);
},
);
}
Widget _buildListItem(DocumentSnapshot document) {
return new ListTile(
title: document['title'],
subtitle: document['subtitle'],
);
}
the main concept is showing document sor fields which contains the searched alphabet
the search bar gets the given input, it send to the _firebasesearch(),but in return nothing comes out, and the above image is my database structure, trying to figure out more than a week,
I'm a bit too late but I just want to share something on how I implement the search function without using third party app in my case. My solution is a bit straight forward querying using firestore. Here's the code:
Future<List<DocumentSnapshot>> getSuggestion(String suggestion) =>
Firestore.instance
.collection('your-collection')
.orderBy('your-document')
.startAt([searchkey])
.endAt([searchkey + '\uf8ff'])
.getDocuments()
.then((snapshot) {
return snapshot.documents;
});
example if you want to search all keywords containing "ab" then it will display all words containing "ab" (ex. abcd, abde, abwe). If you want to make auto suggest search function you can use typehead. which can be found in this link: https://pub.dev/packages/flutter_typeahead
Good luck.
This might sound a ridiculous solution but actually works so well, It's almost like the Like '%' query from SQL
In the TextField as you type a value the inside where() isGreaterThanOrEqualTowill compare it and all the string values greater than the input and If you concatinate a 'Z' At the end then isLessThan will end just after your search keyword and You get the desired Result from firestore.
// Declare your searchkey and Stream variables first
String searchKey;
Stream streamQuery;
TextField(
onChanged: (value){
setState(() {
searchKey = value;
streamQuery = _firestore.collection('Col-Name')
.where('fieldName', isGreaterThanOrEqualTo: searchKey)
.where('fieldName', isLessThan: searchKey +'z')
.snapshots();
});
}),
I used this Stream in StreamBuilder and It works exactly as expected.
Limitations:
You don't have to rebuild your whole stream, just filter the results from your stream depending on your search string. Fast, does not need to rebuild the whole stream, finds occurences of the search string not only from the start of a word and is case-insensitive.
return StreamBuilder(
stream: FirebaseFirestore.instance.collection("shops").snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) // TODO: show alert
return Text('Something went wrong');
if (snapshot.connectionState == ConnectionState.waiting)
return Column(
children: [
Center(
child: CupertinoActivityIndicator()
)
],
);
var len = snapshot.data.docs.length;
if(len == 0)
return Column(
children: [
SizedBox(height: 100),
Center(
child: Text("No shops available", style: TextStyle(fontSize: 20, color: Colors.grey)),
)
],
);
List<Shop> shops = snapshot.data.docs.map((doc) => Shop(
shopID: doc['shopID'],
name: doc['name'],
...
)).toList();
shops = shops.where((s) => s.name.toLowerCase().contains(searchString.text.toLowerCase())).toList();
return
Expanded(
child: ListView.builder(
padding: EdgeInsets.symmetric(vertical: 15),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: shops.length,
itemBuilder: (context, index) {
return shopRow(shops[index]);
}
),
);
},
);
The issue is you are expecting results from firestore where title is equal to queryText
not title contains queryText
.
If you want the search feature, you can get and store the firestore documents
in a variable something like List<Model> model
instead of StreamBuilder
and implement search manually
from the above stored list of model.
THIS IS ANOTHER SEARCH CODE THIS WILL SEARCH INSIDE FIREBASE DATABASE
import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';
class Db extends StatefulWidget {
@override
HomeState createState() => HomeState();
}
class HomeState extends State<Db> {
List<Item> Remedios = List();
Item item;
DatabaseReference itemRef;
TextEditingController controller = new TextEditingController();
String filter;
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
@override
void initState() {
super.initState();
item = Item("", "");
final FirebaseDatabase database = FirebaseDatabase.instance; //Rather then just writing FirebaseDatabase(), get the instance.
itemRef = database.reference().child('Remedios');
itemRef.onChildAdded.listen(_onEntryAdded);
itemRef.onChildChanged.listen(_onEntryChanged);
controller.addListener(() {
setState(() {
filter = controller.text;
});
});
}
_onEntryAdded(Event event) {
setState(() {
Remedios.add(Item.fromSnapshot(event.snapshot));
});
}
_onEntryChanged(Event event) {
var old = Remedios.singleWhere((entry) {
return entry.key == event.snapshot.key;
});
setState(() {
Remedios\[Remedios.indexOf(old)\] = Item.fromSnapshot(event.snapshot);
});
}
void handleSubmit() {
final FormState form = formKey.currentState;
if (form.validate()) {
form.save();
form.reset();
itemRef.push().set(item.toJson());
}
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
centerTitle: true,
backgroundColor: new Color(0xFFE1564B),
),
resizeToAvoidBottomPadding: false,
body: Column(
children: <Widget>\[
new TextField(
decoration: new InputDecoration(
labelText: "Type something"
),
controller: controller,
),
Flexible(
child: FirebaseAnimatedList(
query: itemRef,
itemBuilder: (BuildContext context, DataSnapshot snapshot,
Animation<double> animation, int index) {
return Remedios\[index\].name.contains(filter) || Remedios\[index\].form.contains(filter) ? ListTile(
leading: Icon(Icons.message),
title: Text(Remedios\[index\].name),
subtitle: Text(Remedios\[index\].form),
) : new Container();
},
),
),
\],
),
);
}
}
class Item {
String key;
String form;
String name;
Item(this.form, this.name);
Item.fromSnapshot(DataSnapshot snapshot)
: key = snapshot.key,
form = snapshot.value\["form"\],
name = snapshot.value\["name"\];
toJson() {
return {
"form": form,
"name": name,
};
}
}
The solution that i found:
List<String> listaProcura = List();
String temp = "";
for(var i=0;i<nomeProduto.length; i++) {
if(nomeProduto[i] == " ") {
temp = "";
} else {
temp = temp + nomeProduto[i];
listaProcura.add(temp);
}
}
The "listaProcura" is the name of the list. the String "temp" is the name of a temporary string. This way you will save this list of names in the firebase database. Will be like:
[0] E
[1] Ex
[2] Exa
[3] Exam
[4] Examp
[5] Exampl
[6] Example
[7] o
[8] on
[9] one
For retrieving this info with the word you wanna search:
await Firestore.instance.collection('name of your collection').where('name of your list saved in the firebase', arrayContains: 'the name you are searching').getDocuments();
This way if you search for "one" and the name is "Example one" the search will return properly.
if Search list is case senstive like this :
then :
response = await FirebaseFirestore.instance
.collection('pointOFSale')
.orderBy("title")
.startAt([val.capitalize()]).endAt(
[val[0].toUpperCase() + '\uf8ff']).get();
Extension code :
extension StringExtension on String {
String capitalize() {
return "${this[0].toUpperCase()}${this.substring(1)}";
}
}
if List is like :
then :
response = await FirebaseFirestore.instance
.collection('pointOFSale')
.orderBy("title")
.startAt([val]).endAt([val + '\uf8ff']).get();
You can use https://pub.dev/packages/firestore_search package, with less code and more efficiency.
soo simple and fast.
if (text.length > 1) {
setState(() {
tempSearchStore = _listPkh.documents.where((d) {
if (d['nama'].toLowerCase().indexOf(text) > -1) {
return true;
} else if (d['alamat'].toLowerCase().indexOf(text) > -1) {
return true;
}
return false;
}).toList();
});
} else {
setState(() {
tempSearchStore = _listPkh.documents;
});
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.