Attaching Index To List Item (string) [Flutter] - list

Instead of making isSelected bool variable, i'll like to make it as index of selected. then check for the index of selected in reportReasons list.
This is to know which reason is being selected. Also, how do I then make the selected container change color if isSelected is not a bool?
Thank you.
final List<String> reportReasons = [
'blah',
'blah blah',
'blah blah blah'
];
List<String> chosenReasonsToReport = [];
bool isSelected = false;
Container(
child: Wrap(
children: reportReasons
.map((reportReason) => GestureDetector(
onTap: () {
setState(() { if (isSelected = false) {
isSelected = true;
} else {
isSelected = false;
}});
if (reportReason.isSelected && chosenReasonsToReport.length < 3) {
chosenReasonsToReport.add('${reportReason}');
print(chosenReasonsToReport);
} else {
chosenReasonsToReport.remove('${reportReason}');
print(chosenReasonsToReport);
}
},
child: Container(
margin: EdgeInsets.only(
right:
MediaQuery.of(context).size.width * 0.021,
bottom: MediaQuery.of(context).size.height *
0.009,
),
decoration: BoxDecoration(
color: isSelected
? Color(0xff4aa3f8)
: Color(0xff3a327f),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color:
Colors.grey[50].withOpacity(0.60))),
padding: EdgeInsets.symmetric(
horizontal:
MediaQuery.of(context).size.width *
0.027,
vertical:
MediaQuery.of(context).size.height *
0.0045),
child: Text(
reportReason,
style: TextStyle(
fontSize: 13.5,
color: isSelected
? Color(0xff231b6a)
: null),
),
),
))
.toList()),

You can use a couple of approaches:
A set of indexes:
class _MyScreenState extends State<MyScreen> {
static const List<String> _reportReasons = [
'blah',
'blah blah',
'blah blah blah'
];
Set<int> _chosenIndexes = {};
#override
Widget build(BuildContext context) {
return ListView(
children: List.generate(_reportReasons.length, (i) {
return Container(
// Change property based on report selection
color: _chosenIndexes.contains(i)
? Colors.green
: Colors.red,
child: CheckboxListTile(
// Accessing report name
title: Text(_reportReasons[i]),
// Accessing if report is selected
value: _chosenIndexes.contains(i),
// Selecting and unselecting report
onChanged: (v) {
setState(() {
if (v) {
_chosenIndexes.add(i);
} else {
_chosenIndexes.remove(i);
}
});
}
),
);
}),
);
}
}
A map of String and booleans:
class _MyScreenState extends State<MyScreen> {
final Map<String, bool> _reports = {
'blah': false,
'blah blah': false,
'blah blah blah': false,
};
#override
Widget build(BuildContext context) {
return ListView(
children: _reports.keys.map((report) {
return Container(
// Change property based on report selection
color: _reports[report]
? Colors.green
: Colors.red,
child: CheckboxListTile(
// Accessing report name
title: Text(report),
// Accessing if report is selected
value: _reports[report],
// Selecting and unselecting report
onChanged: (v) {
setState(() => _reports[report] = v);
}
),
);
}).toList(),
);
}
}

Related

how to make history with textfield in flutter?

class _SimpleDialogState extends State<SimpleDialog> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final TextEditingController _textEditingController = TextEditingController();
#override
void initState() {
super.initState();
baseurl = Prefs().geturlBase();
}
#override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('Base URL'),
content: Form(
key: _formKey,
child: TextFormField(
keyboardType: TextInputType.multiline,
maxLines: null,
//controller: _textEditingController,
initialValue: baseurl,
onChanged: (val) {
setState(() {
baseurl = val;
print(baseurl);
});
},
decoration: InputDecoration(
hintText: "Please Enter Base Url",
border:
OutlineInputBorder(borderRadius: BorderRadius.circular(15)),
),
validator: (value) {
// return value!.isNotEmpty ? null : "Enter Base Url";
return Uri.parse(value.toString()).host == ''
? "Enter Base Url"
: null;
},
)),
actions: <Widget>[
Center(
child: InkWell(
onTap: () {
buildShowDialog(context);
if (_formKey.currentState!.validate()) {
baseurl = baseurl.trim();
checkBaseUrl(baseurl, context);
// Navigator.of(context).pop();
print('baseurl=====base------$baseurl');
}
},
child: Container(
width: 100,
height: 40,
padding: EdgeInsets.all(12.0),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(20.0),
),
child: Text(
"Connect",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
),
),
)
],
);
}
}
This is a dialog box where I can change my baseURL. Now, I need history when I touch textfield, history should appear and I can able to select the data from history to text field and also able to delete history, not all history particular data from that list. how can I able to achieve this kinda logic??.
An input_history_text_field widget is automatically saved and suggested as you type.

Adding words to the list in the correct order

I'm trying to adjust the words to form the sentence in the correct order. Like this. Or like Duolingo sentence examples. (without drag and drop, just lists and/or maps)
Sentence:
static String mySentence = "My cat is black";
static List<String> correctWords = mySentence.split(" ");
static List<String> shuffleWords = [...correctWords]..shuffle();
Green part: shuffleWidgetList. A widget has been added to each word in the shuffleWords.
List<Widget> shuffleWidgetList = [];
generateShuffleWidgets() {
for (int i = 0; i < shuffleWords.length; i++) {
shuffleWidgetList.add(shuffleWordWidget(shuffleWords[i]));
}
}
Blue part: answerWidgetList.
List<Widget> answerWidgetList = [];
White part: The answer is checked with the button.
I am comparing the list of words (List<String>) correctWords with answerWords.
onTap: () {
if (IterableEquality().equals(correctWords, answerWords)) {
print("correct");
} else {
print("wrong");
}
},
Steps:
1. In the green part, I choose a word from the list. The item I clicked on is added to the answerWidgetList (blue part). And removed from shuffleWidgetList (green part).
onTap: () {
setState(() {
shuffleWidgetList.remove(shuffleWordWidget(word));
//not necessary remove. Look at Problem 1.a
answerWidgetList.add(answerWordWidget(word));
answerWords.add(word);
});
},
2. Clicking on a word in the blue part adds it to its old place in the shuffleWidgetList(green part). And it is removed from answerWidgetList (blue part).
onTap: () {
setState(() {
shuffleWidgetList.add(shuffleWordWidget(word)); //Problem 1.b
answerWidgetList.remove(answerWordWidget(word)); //Problem 2
answerWords.remove(word);
});
},
Problems:
1.a. How can I change shuffleWordWidget's text color when I click an item in shuffleWidgetList?
I tried: In the shuffleWidgetList(green part) it is unnecessary to remove the item when clicking. Text should be transparent (to keep the widget size) and not be clicked again. For this I added bool clicked=false; to shuffleWordWidget. When clicked, onTap() updates to true, but color doesn't update. Like this:
shuffleWordWidget(String word) {
bool clicked = false;
return InkWell(
child: Container(
color: clicked == false ? Colors.white54 : Colors.grey,
child: Text(
word,
style: TextStyle(fontSize: 12,color:clicked == false ? Colors.black : Colors.transparent ),
),
),
onTap: () {
if (clicked == false) {
setState(() {
...
clicked = true;
});
}
},
);
}
1.b. How can I add shuffleWidgetList to its old place when an item is clicked in answerWidgetList?
For old place; that if the user clicks on a word from the answerWidgetList(blue part), it should be the same word clicked=false; again in the shuffleWidgetList(green part).
2. How can I remove item from answerWidgetList when I click an item in answerWidgetList?
answerWidgetList.remove(answerWordWidget(word)); doesn't work.
My approach may be completely wrong. You can also suggest different solutions.
Full code:
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Sentence Creation',
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
static String mySentence = "My cat is black";
static List<String> correctWords = mySentence.split(" ");
static List<String> shuffleWords = [...correctWords]..shuffle();
List<String> answerWords = [];
List<Widget> shuffleWidgetList = [];
List<Widget> answerWidgetList = [];
generateShuffleWidgets() {
for (int i = 0; i < shuffleWords.length; i++) {
shuffleWidgetList.add(shuffleWordWidget(shuffleWords[i]));
}
}
#override
void initState() {
super.initState();
generateShuffleWidgets();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
flex: 2,
child: Container(
color: Colors.blue,
child: Center(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: answerWidgetList,
),
),
)),
Expanded(
child: Container(
color: Colors.green,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: shuffleWidgetList,
),
),
),
SizedBox(
height: 50,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
child: Center(child: Text("Check")),
onTap: () {
if (IterableEquality().equals(correctWords, answerWords)) {
print("correct");
} else {
print("wrong");
}
print("correct list: $correctWords");
print("answer list: $answerWords");
},
),
),
)
],
),
);
}
shuffleWordWidget(String word) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: InkWell(
child: Container(
color: Colors.white54,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
word,
style: TextStyle(fontSize: 12),
),
),
),
onTap: () {
setState(() {
shuffleWidgetList.remove(shuffleWordWidget(word));
//not necessary remove. Look at Problem 1.a
answerWidgetList.add(answerWordWidget(word));
answerWords.add(word);
});
},
),
);
}
answerWordWidget(String word) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: InkWell(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
word,
style: TextStyle(fontSize: 12),
),
),
),
onTap: () {
setState(() {
shuffleWidgetList.add(shuffleWordWidget(word)); //Problem 1.b
answerWidgetList.remove(answerWordWidget(word)); //Problem 2
answerWords.remove(word);
});
},
),
);
}
}
Put this code in _HomePageState.
static String mySentence = "My cat is black";
static List<String> correctWords = mySentence.split(" ");
static List<String> shuffleWords = [...correctWords]..shuffle();
List<String> answerWords = [];
List<Widget> shuffleWidgetList = [];
List<Widget> answerWidgetList = [];
generateShuffleWidgets() {
for (int i = 0; i < shuffleWords.length; i++) {
shuffleWidgetList.add(shuffleWordWidget(shuffleWords[i],true));
}
}
#override
void initState() {
super.initState();
generateShuffleWidgets();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
flex: 2,
child: Container(
color: Colors.blue,
child: Center(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: answerWidgetList,
),
),
)),
Expanded(
child: Container(
color: Colors.green,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: shuffleWidgetList,
),
),
),
SizedBox(
height: 50,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
child: Center(child: Text("Check")),
onTap: () {
if (IterableEquality().equals(correctWords, answerWords)) {
print("correct");
} else {
print("wrong");
}
print("correct list: $correctWords");
print("answer list: $answerWords");
},
),
),
)
],
),
);
}
shuffleWordWidget(String word,bool visible) {
return Visibility(
visible: visible,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: InkWell(
child: Container(
color: Colors.white54,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
word,
style: TextStyle(fontSize: 12),
),
),
),
onTap: () {
setState(() {
//shuffleWidgetList.remove(shuffleWordWidget(word));
int i = shuffleWords.indexOf(word);
shuffleWidgetList[i]=shuffleWordWidget(word,false);
//not necessary remove. Look at Problem 1.a
answerWidgetList.add(answerWordWidget(word));
answerWords.add(word);
});
},
),
),
);
}
answerWordWidget(String word) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: InkWell(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
word,
style: TextStyle(fontSize: 12),
),
),
),
onTap: () {
setState(() {
int i = shuffleWords.indexOf(word);
// shuffleWidgetList.insert(i,shuffleWordWidget(word)); //Problem 1.b
shuffleWidgetList[i]=shuffleWordWidget(word,true);
int y = answerWords.indexOf(word);
answerWidgetList.removeAt(y); //Problem 2
answerWords.remove(word);
});
},
),
);
}
I added a visibility detector which is triggered with a bool value. I used the shuffleWords list to get the index of the widget and hid it by changing the bool to false. Similarly answerWords can be used for removing widgets from answerWidgetList. As the widget from answerWidgetList is removed therefore we don't need visibility widget there.
Or if shuffleWordWidget is replaced with this then Visibility() is not needed and the image in the question is obtained.
shuffleWordWidget(String word, bool visible) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: InkWell(
child: Container(
color: visible == true ? Colors.white54 : Colors.grey,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
word,
style: TextStyle(
fontSize: 12,
color: visible == true ? Colors.black : Colors.transparent),
),
),
),
onTap: () {
if (visible == true) {
setState(() {
//shuffleWidgetList.remove(shuffleWordWidget(word));
int i = shuffleWords.indexOf(word);
shuffleWidgetList[i] = shuffleWordWidget(word, false);
//not necessary remove. Look at Problem 1.a
answerWidgetList.add(answerWordWidget(word));
answerWords.add(word);
});
}
},
),
);
}

Selecting from a dropdown list and updating the same list the same time in flutter

How do I ensure that a user does not select the same security question twice by hiding the initially selected question from appearing in the second dropdown button and vice versa in flutter?. i am making a request to the same api for the questions.
Updated the question with some code snippets. Thanks
Container(
height: 60,
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(color: Colors.black,
width: 1),
borderRadius: BorderRadius.circular(5),
),
child: DropdownButtonHideUnderline(
child: DropdownButton(
hint: Padding(
padding: const EdgeInsets.only(left:
20.0),
child: Text(
"Security Question Two",
style: TextStyle(
color: Colors.black,
fontSize: 16,
letterSpacing: 0.3,
fontWeight: FontWeight.w300),
),
),
itemHeight: 100,
isExpanded: true,
value: dropDownSecurityQuestionTwo,
icon: Padding(
padding: const EdgeInsets.only(right:
10.0),
child:
Icon(Icons.keyboard_arrow_down_outlined),
),
iconEnabledColor: Colors.black,
iconSize: 30,
style: TextStyle(
color: Colors.black,
),
items: questions.map((value) {
return DropdownMenuItem(
value: value['ID'].toString(),
child: Padding(
padding: const EdgeInsets.only(left:
20.0),
child: Text(
value['question'].toString(),
),
),
);
}).toList(),
onChanged: (newValue) async {
setState(() {
dropDownSecurityQuestionTwo =
newValue.toString();
print(dropDownSecurityQuestionTwo);
checkSelectedQuestion();
});
},
),
),
),
void checkSelectedQuestion(){
List newQuestions = [];
for(int i = 0; i<questions.length; i++){
print(questions[i]['ID']);
questions.removeWhere((value) => value['ID'] ==
int.parse(dropDownSecurityQuestionOne!) );
newQuestions.add(questions);}
setState(() {
questions = newQuestions ;
});}
You can add a where filter to the mapping of items to each DropDownButton, depending on the selected value of the other DropDownButton. As a result of setState, the items will be recreated if anything is selected in the other DropDownButton.
Note: This is easy to implement, but not very efficient. Items will be created and filtered every time. It will work perfectly with few items, but if you would like to do something like this with many items, you might need a more efficient approach. For example keep two items lists, and only add / remove what is affected.
Check this code and adopt it to your case:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyPage(),
);
}
}
class MyPage extends StatefulWidget {
const MyPage({Key? key}) : super(key: key);
#override
State<MyPage> createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> {
String? _selected1;
String? _selected2;
final List<String> _set = ['Alpha', 'Bravo', 'Charlie'];
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(children: [
DropdownButton<String>(
value: _selected1,
onChanged: (String? newValue) {
setState(() {
_selected1 = newValue!;
});
},
items: _set
.map((value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
})
.where((e) => _selected2 == null || e.value != _selected2)
.toList()),
DropdownButton<String>(
value: _selected2,
onChanged: (String? newValue) {
setState(() {
_selected2 = newValue!;
});
},
items: _set
.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
})
.where((e) => _selected1 == null || e.value != _selected1)
.toList()),
]),
),
),
);
}
}

Change Colors of Selected Containers and Unselect? [Flutter]

They are containers filled with reasons to report a user.
How to change the code so that each individual container will change color upon tab on/off?
And also limit the selected reasons to 3 while printing the reasons to the chosenReportReasons list?
Attached is the truncated code:
final List<String> reportReasons = [
'blah',
'blah blah',
'blah blah blah'
];
List<String> chosenReasonsToReport = [];
bool isSelected = false;
Container(
child: Wrap(
children: reportReasons
.map((reportReason) => GestureDetector(
onTap: () {
if (isSelected = false) {
isSelected = true;
} else {
isSelected = false;
}
setState(() {});
if (reportReason.isSelected && chosenReasonsToReport.length < 3) {
chosenReasonsToReport.add('${reportReason}');
print(chosenReasonsToReport);
} else {
chosenReasonsToReport.remove('${reportReason}');
print(chosenReasonsToReport);
}
},
child: Container(
margin: EdgeInsets.only(
right:
MediaQuery.of(context).size.width * 0.021,
bottom: MediaQuery.of(context).size.height *
0.009,
),
decoration: BoxDecoration(
color: isSelected
? Color(0xff4aa3f8)
: Color(0xff3a327f),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color:
Colors.grey[50].withOpacity(0.60))),
padding: EdgeInsets.symmetric(
horizontal:
MediaQuery.of(context).size.width *
0.027,
vertical:
MediaQuery.of(context).size.height *
0.0045),
child: Text(
reportReason,
style: TextStyle(
fontSize: 13.5,
color: isSelected
? Color(0xff231b6a)
: null),
),
),
))
.toList()),
Updated error of code
Further Updated:
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: ReportPage(),
);
}
}
class RemarksModel {
bool isSelected;
String reason;
RemarksModel({this.isSelected, this.reason});
}
class ReportPage extends StatefulWidget {
List<RemarksModel> reportReasons;
#override
void initState() {
super.initState();
reportReasons = [
RemarksModel(isSelected: false, reason: 'Sexually Harassing'),
RemarksModel(isSelected: false, reason: 'Racially Discriminative'),
RemarksModel(isSelected: false, reason: 'Shouting'),
RemarksModel(isSelected: false, reason: 'Prank Calling'),
RemarksModel(isSelected: false, reason: 'Scam Bots'),
RemarksModel(isSelected: false, reason: 'Vulgarities Abusing'),
RemarksModel(isSelected: false, reason: 'No Sound')
];
}
#override
_ReportPageState createState() => _ReportPageState();
}
class _ReportPageState extends State<ReportPage> {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
...
For the ease create a Model class for Reasons
class RemarksModel {
bool isSelected;
String reason;
RemarksModel({this.isSelected, this.reason});
}
and can be initialized as
List<RemarksModel> reportReasons;
#override
void initState() {
super.initState();
reportReasons = [
RemarksModel(isSelected: false, reason: 'blah'),
RemarksModel(isSelected: false, reason: 'blah blah'),
RemarksModel(isSelected: false, reason: 'blah blah blah')
];
}
then you can easily know whether the item is selected or not, and you can make an item select and deselect on the tap callback
onTap: () {
setState(() {
reportReason.isSelected = !reportReason.isSelected;
});
},
Full code
#override
Widget build(BuildContext context) {
return Container(
child: Wrap(
children: reportReasons
.map((reportReason) => GestureDetector(
onTap: () {
setState(() {
reportReason.isSelected = !reportReason.isSelected;
});
},
child: Container(
margin: EdgeInsets.only(
right: MediaQuery.of(context).size.width * 0.021,
bottom: MediaQuery.of(context).size.height * 0.009,
),
decoration: BoxDecoration(
color: reportReason.isSelected
? Color(0xff4aa3f8)
: Color(0xff3a327f),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: Colors.grey[50].withOpacity(0.60))),
padding: EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width * 0.027,
vertical:
MediaQuery.of(context).size.height * 0.0045),
child: Text(
reportReason.reason,
style: TextStyle(
fontSize: 13.5,
color: reportReason.isSelected
? Color(0xff231b6a)
: null),
),
),
))
.toList()),
);
}
if you need a list of selected reasons only,
List<RemarksModel> getSelectedReasons() {
return reportReasons.where((reason) => reason.isSelected).toList();
}
try wrap these lines inside a setState:
if (isSelected = false) {
isSelected = true;
} else {
isSelected = false;
}
and remove the setState below.

Firebase List in flutter

I implemented a search list with consultation to firebase. Initially, all registered users appear on the screen and when I click on one of the users, the app shows another screen with all the data for that user. When you start typing in the search field, only users with respect to the text entered appear.
However, a problem arose: when filtering a customer, only it appears on the screen and when I click to open the customer's information, the app shows the information of the first user in the general list (without taking into account the filter).
I believe that this happens due to the index, which looks at the position of the document in the firebase.
How to fix this? Thank you!
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
Step 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}';
}
Step 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);
}
}
}
Step 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)));
},
);
},
),
),
],
);
}
});
});
}
},
)));
}
Step 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()}'),
],
),
);
}
}
<blockquote class="imgur-embed-pub" lang="en" data-id="a/aqBaJ7N" data-context="false" ></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>
Hey! Unfortunately it didn't work, look what keeps happening.
I think this is because of the index I send as a parameter, which does not understand that the values have been filtered:
onTap: ()=> {
//print(data.documentID),
_navegarParaPerfil(context, items[index]),
}
void _navegarParaPerfil(BuildContext context, Paciente paciente) async{
await Navigator.push(context,
MaterialPageRoute(builder: (context) => TelaPaciente(paciente)),
);
}
Ideally, it would be validated by documentID instead of this index, but I was unable to change it