我实施了一个搜索列表,并咨询了 firebase。最初,所有注册用户都出现在屏幕上,当我单击其中一个用户时,应用程序会显示另一个屏幕,其中包含该用户的所有数据。当您开始在搜索字段中输入时,只会显示与输入文本相关的用户。
然而,出现了一个问题:过滤一个客户时,只出现在屏幕上,当我点击打开客户的信息时,应用程序显示了通用列表中第一个用户的信息(不考虑过滤器).
我相信这是由于索引导致的,它查看文档在 firebase 中的位置。
如何解决这个问题?谢谢!
body: Column(
children: <Widget>[
SizedBox(
height: 5,
),
TextField(
controller: _procurarpaciente,
decoration: InputDecoration(
border: OutlineInputBorder(), labelText: "Pesquisar paciente",prefixIcon: Icon(Icons.search)
),
onChanged: (val) {
setState(() {
nome = val;
});
},
),
Expanded(
child: StreamBuilder<QuerySnapshot>(
stream: (nome != "" && nome != null)
? Firestore.instance
.collection('pacientes')
.where("indexList", arrayContains: nome)
.snapshots()
: Firestore.instance.collection("pacientes").snapshots(),
builder: (context, snapshot) {
switch(snapshot.connectionState){
case ConnectionState.none:
case ConnectionState.waiting:
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.error_outline),
Text("Usuário não encontrado")
],
),
);
default:
// List<DocumentSnapshot> documentos =
// snapshot.data.documents;
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot data = snapshot.data.documents[index];
return ListTile(
title: Text(
data['nome'],
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 16,
),),
subtitle:Text(
"Quarto: ${data['quarto']}",
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 14,
),),
leading:CircleAvatar(
backgroundImage: NetworkImage(data['foto']),
),
onTap: ()=> {
//print(data.documentID),
_navegarParaPerfil(context, items[index]),
}
);
},
);
}
}
),
)
],
),
void _navegarParaPerfil(BuildContext context, Paciente paciente) async{
await Navigator.push(context,
MaterialPageRoute(builder: (context) => TelaPaciente(paciente)),
);
}
dsdsd
答案 0 :(得分:0)
第 1 步:
class Employee {
Employee(this.employeeID, this.employeeName, this.branch, this.designation, this.location,
this.salary,
{this.reference});
double employeeID;
String employeeName;
String designation;
String branch;
String location;
double salary;
DocumentReference reference;
factory Employee.fromSnapshot(DocumentSnapshot snapshot) {
Employee newEmployee = Employee.fromJson(snapshot.data());
newEmployee.reference = snapshot.reference;
return newEmployee;
}
factory Employee.fromJson(Map<String, dynamic> json) =>
_employeeFromJson(json);
Map<String, dynamic> toJson() => _employeeToJson(this);
@override
String toString() => 'employeeName ${employeeName}';
}
第 2 步:
class EmployeeRepository {
List<Employee> employees = [];
final CollectionReference collection =
FirebaseFirestore.instance.collection('employees');
Stream<QuerySnapshot> getStream() {
return collection.snapshots();
}
Future<DocumentReference> add(Employee employee) {
var documentReference = collection.add(employee.toJson());
return documentReference;
}
update(Employee employee) async {
collection.doc(employee.reference.id).update(employee.toJson());
}
delete(Employee employee) async {
collection.doc(employee.reference.id).delete();
}
fromSnapShot(DocumentSnapshot snapshot) => Employee.fromSnapshot(snapshot);
Future<List<Employee>> buildData(
AsyncSnapshot snapshot, String filterKey) async {
List<Employee> list = [];
List<Employee> filteredList = [];
/// Based on the user snapShot, you can convert into the List and return to
/// the futurebuilder
await Future.forEach(snapshot.data.docs, (element) async {
list.add(Employee.fromSnapshot(element));
}).then((value) {
if (filterKey != null) {
filteredList = list
.where((element) =>
element.employeeID.toString() == filterKey ||
element.employeeName == filterKey ||
element.designation == filterKey ||
element.branch == filterKey ||
element.location == filterKey ||
element.salary.toString() == filterKey)
.toList();
}
});
if (filteredList.isEmpty) {
return Future<List<Employee>>.value(list);
} else {
return Future<List<Employee>>.value(filteredList);
}
}
}
第 3 步:
EmployeeRepository employeeRepository = EmployeeRepository();
TextEditingController textEditingController = TextEditingController();
String filteredText = '';
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('ListView'),
),
body: StreamBuilder(
stream: employeeRepository.getStream(),
builder: (context, snapShot) {
if (snapShot.data == null ||
snapShot.connectionState == ConnectionState.waiting ||
snapShot.hasError ||
snapShot.data.docs.length == 0) {
return Container(
child: Center(child: CircularProgressIndicator()),
);
} else {
return StatefulBuilder(builder: (context, innerSetState) {
return FutureBuilder(
future: employeeRepository.buildData(
snapShot, filteredText),
builder: (context, futureSnapShot) {
if (!futureSnapShot.hasData) {
return Container(
child: Center(child: CircularProgressIndicator()),
);
} else {
return Column(
children: [
TextField(
controller: textEditingController,
decoration: InputDecoration(
icon: Icon(Icons.search),
hintText: 'Search here!'),
onSubmitted: (value) {
innerSetState(() {
filteredText = value;
});
},
onChanged: (value) {
innerSetState(() {
filteredText = value;
});
},
),
Container(
height: 400,
child: ListView.builder(
itemCount: futureSnapShot.data.length,
itemBuilder: (context, index) {
final Employee employee =
futureSnapShot.data[index];
return ListTile(
title: Text(employee.employeeName),
trailing:
Text('Salary${employee.salary}'),
subtitle: Text(employee.designation),
onTap: () {
print(employee.salary);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
EmployeeDetailsPage(
employee)));
},
);
},
),
),
],
);
}
});
});
}
},
)));
}
第 4 步:
class EmployeeDetailsPage extends StatelessWidget {
final Employee employeeData;
const EmployeeDetailsPage(this.employeeData);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Employee Details'),
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Center(child: Text(employeeData.employeeName, style: TextStyle(fontSize: 30))),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Center(child: Text(employeeData.designation, style: TextStyle(fontSize: 20))),
),
Text('Salary ${employeeData.salary.toString()}'),
],
),
);
}
}
答案 1 :(得分:0)
<blockquote class="imgur-embed-pub" lang="en" data-id="a/aqBaJ7N" data-context="false" ><a href="//imgur.com/a/aqBaJ7N"></a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>
嘿!不幸的是它没有用,看看发生了什么。
我认为这是因为我作为参数发送的索引,它不明白这些值已经被过滤了:
onTap: ()=> {
//print(data.documentID),
_navegarParaPerfil(context, items[index]),
}
void _navegarParaPerfil(BuildContext context, Paciente paciente) async{
await Navigator.push(context,
MaterialPageRoute(builder: (context) => TelaPaciente(paciente)),
);
}
理想情况下,它将通过 documentID 而不是此索引进行验证,但我无法更改它