Related
My app is simple Authentication todo app where I store authenticate user UID in firestore document red mark represents login user UID and blue mark represents tasks of that particular user of below image.
Firestore image
Using QuerySnapshot I am trying to get particular user data but my code is not working dynamically.
I wanted to get particular user content array data and login user uid is same as document id here is my code.
StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('Users').snapshots(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(
child: Text(
'Some thing went wrong! \n Restart your app!',
style: TextStyle(fontSize: 28.0, color: Colors.red),
));
} else if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(
color: Colors.cyan,
));
} else if (snapshot.hasData || snapshot.data != null) {
return ListView.builder(
shrinkWrap: true,
//------ This is static how to do it dynamically where only particular user content length will get?
itemCount: snapshot.data?.docs[1]['content'].length,
itemBuilder: (BuildContext context, int index) {
//------ This is static how to do it dynamically where I know that 1 index user is login that's why I gave index 1 how to do it dynamic?
DocumentSnapshot? documentSnapshot = snapshot.data?.docs[1];
return Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 8.0),
child: Card(
color: Colors.black,
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 20.0, horizontal: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: GestureDetector(
onTap: () async {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Edit Task'),
content: TextFormField(
controller: editTodoController,
decoration: InputDecoration(
hintText: 'Task info.',
errorText: _validate ? "Enter task" : null,
// label: Text("Task info"),
),
),
actions: [
TextButton(
onPressed: () async {
try {
final contentList = _firestore.collection('Users').doc(_user?.uid);
final docSnap = await contentList.get();
List content = docSnap.get('content');
ref.update({
'content': FieldValue.arrayRemove([content[index]]),
});
ref.update({
'content': FieldValue.arrayUnion([editTodoController.text]),
});
setState(() {
if (editTodoController.text.isEmpty) {
_validate = true;
} else {
_validate = false;
Navigator.of(context).pop();
}
editTodoController.clear();
// addTodoController.text.isEmpty ? _validate = true : _validate = false;
});
} catch (e) {
print(e);
}
},
child: Text('UPDATE'),
)
],
),
);
},
child: Text(
'${documentSnapshot!['content'][index]}',
// '${index} \t ${todoList[index]}',
style:
TextStyle(fontSize: 20.0, color: Colors.white),
),
),
),
IconButton(
onPressed: () async {
try {
final contentList = _firestore.collection('Users').doc(_user?.uid);
final docSnap = await contentList.get();
List content = docSnap.get('content');
await ref.update({
'content': FieldValue.arrayRemove([content[index]]),
});
} catch (e){
print(e);
}
},
icon: Icon(Icons.delete, color: Colors.white54, size: 29.0,)
),
],
),
),
),
);
},
);
}
return CircularProgressIndicator();
})
I am developing a feature where the user enters a sentence, in the next screen the words of that sentence get shuffled randomly, then the user has to drag the words to a drag target to form the original sentence.
You can get an idea from the screenshots below.
First screen
Second screen
Now the problem I am having is, when dragging the words to the target I can see the DragTarget is calling onWillAccept as I added a print() statement there, if it is doing so then it should call onAccept eventually but it is not doing so. This is why my codes that deal with Bloc are not getting called and the words are not showing up in the target spot.
Code
class SentenceMakeScreen extends StatefulWidget {
String inputSentence;
SentenceMakeScreen(this.inputSentence);
#override
State<SentenceMakeScreen> createState() => _SentenceMakeScreenState();
}
class _SentenceMakeScreenState extends State<SentenceMakeScreen> {
List<String> sentence = [];
List<Widget> wordWidgets = [];
bool isDragSuccessful = false;
final ButtonStyle _buttonStyle = ElevatedButton.styleFrom(
textStyle: TextStyle(fontSize: 20)
);
_getTextWidgets(List<String> sentence) {
for(var i = 0; i < sentence.length; i++){
wordWidgets.add(
Draggable<WordWidget>(
data: WordWidget(sentence[i]),
child: WordWidget(sentence[i]),
feedback: WordWidget(sentence[i]),
childWhenDragging: Container(),
)
);
}
}
_randomlyOrganizeSentence(String inputString) {
sentence = inputString.split(new RegExp(r" "));
sentence.shuffle();
print(sentence);
}
#override
void initState() {
// TODO: implement initState
_randomlyOrganizeSentence(widget.inputSentence);
_getTextWidgets(sentence);
super.initState();
}
#override
Widget build(BuildContext context) {
final _dragDropBloc = DragDropBloc();
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context);
},
),
),
body: Container(
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
DragTarget<WordWidget>(
builder: (context, data, rejectedData) {
return Center(
child: this.isDragSuccessful
?
Container(
width: double.maxFinite,
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.white,
border: Border(
bottom: BorderSide(width: 1.0, color: Colors.black),
),
),
child: StreamBuilder<List<WordWidget>>(
stream: _dragDropBloc.widgetStream,
initialData: [],
builder: (BuildContext context, AsyncSnapshot<List<WordWidget>> snapshot) {
print("Here ${snapshot.data}");
return Wrap(
direction: Axis.horizontal,
children: [
//correctly ordered words
],
);
},
),
)
:
Container(
width: double.maxFinite,
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.white,
border: Border(
bottom: BorderSide(width: 1.0, color: Colors.black),
),
),
child: Text("Drag here")
),
);
},
onWillAccept: (data) {
print("true");
return true;
},
onAccept: (data) {
print(data.toString());
_dragDropBloc.dragDropEventSink.add(
DropEvent(WordWidget(data.toString()))
);
setState(() {
this.isDragSuccessful = true;
//draggedWords.add(data.toString());
});
},
),
Wrap(
direction: Axis.horizontal,
children: wordWidgets
),
Container(
child: ElevatedButton(
style: _buttonStyle,
onPressed: () {
},
child: Text("Check"),
),
),
],
),
),
);
}
}
WordWidget
import 'package:flutter/material.dart';
class WordWidget extends StatelessWidget {
final String word;
const WordWidget(this.word);
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.red[900],
border: Border.all(
width: 4,
color: Colors.black
),
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: EdgeInsets.all(5),
child: Text(
word,
style: TextStyle(
color: Colors.white
),
)
),
);
}
}
I tried adding the type of data I am passing from Draggable to DragTarget, this is what was advised here. It did not work.
I was also getting the same error earlier today. I then upgraded my flutter to the latest version and wrote the DragTarget code again from scratch. I don't know what worked for me but you can try doing the same.
I am trying to create Read and Unread Message feature in my chat application.
So far I can create only Unread, which means when I send Message to firebase collection, I decleared my
READ property field as FALSE,
I am confused how the second user will change the value of the "READ: TRUE" back if he checks the chat room, and if the second user is currently in the chat room he should still change the READ: true.
here is the my send message data:
sender_id:12233,
reciever_id: 6767,
message:'hello please help',
read: false,
here is my code
StreamBuilder(
stream: firestore
.collection('chat')
.doc(widget.peerid)
.collection('Messages')
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
if (snapshot.data.docs.isEmpty) {
return Center(
child: Column(
children: [
Container(
child: Icon(
FontAwesomeIcons.comments,
size: 40,
),
),
Text(
'Say Hello',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
)
],
),
);
}
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
final authid =
snapshot.data.docs[index].data()['idFrom'];
final msg =
snapshot.data.docs[index].data()['content'];
bool check =
authid == auth.currentUser.uid ? true : false;
return Padding(
padding: EdgeInsets.symmetric(
horizontal: 15,
vertical: 10,
),
child: Column(
crossAxisAlignment: check
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: check
? Colors.indigo
: Colors.white,
borderRadius: check
? BorderRadius.only(
bottomLeft: Radius.circular(30),
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
)
: BorderRadius.only(
bottomRight:
Radius.circular(30),
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
child: ConstrainedBox(
constraints:
BoxConstraints(maxWidth: 150),
child: Column(
children: [
Text(
msg,
style: GoogleFonts.raleway(
textStyle: TextStyle(
color: check
? Colors.white
: Colors.black,
),
),
),
Text('')
],
),
),
)
],
),
);
});
}),
),
),
Container(
height: Platform.isIOS ? 95 : 80,
padding: EdgeInsets.only(top: 8.0),
decoration: BoxDecoration(
borderRadius:
BorderRadius.only(topRight: Radius.circular(70)),
color: Theme.of(context).backgroundColor,
),
child: ListTile(
leading: Icon(
Icons.add,
color: Theme.of(context).primaryColor,
),
title: TextFormField(
controller: messagesController,
onChanged: (value) {
messagesController.text = value;
},
decoration: InputDecoration(
hintText: 'Enter your messgae here...',
border: InputBorder.none,
),
maxLines: null,
),
trailing: messagesController.text.trim() == null
? Container(
width: 40,
height: 45,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
Constants.color1,
Constants.color2,
],
),
),
child: GestureDetector(
onTap: () async {
await ControllerApi().sendMessage(
content: messagesController.text.trim(),
chatID: widget.peerid,
messageType: 'text',
myID: auth.currentUser.uid,
selectedUserID: widget.userid,
);
},
child: Icon(
Icons.send,
size: 20,
color: Colors.white,
),
),
)
: Container(),
),
)
],
Thanks.
let's write a function that marks the opponent's messages as read.
Future<void> seeMsg(int peerId) async{
final query = await FirebaseFirestore.instance
.collection('chat')
.doc(peerId)
.collection('Messages')
.where('sender_id', isEqualTo: peerId)
.where('read', isEqualTo: false)
.get();
query.docs.forEach((doc) {
doc.reference.update({'read': true});
});
}
Then, call this function inside StreamBuilder body.
Every time, a new message is generated inside this chat collection, this function checks for unread messages from your peer and marks them as read.
Inside your chat app, when you load messages to user, lets say you already have loaded messages and have a List<Message> messages.
Lets say you show messages with ListView.builder:
return ListView.builder(
shrinkWrap: true,
controller: _controller,
reverse: true,
itemCount: messages.length,
itemBuilder: (context, index) {
final message = messages[index];
// We check if message is new (dont know your entity so lets say it has boolean `read`, that false when new.
final bool isNew = !message.read;
// Given that you store your fire id in myId variable we check if message is received and not sent.
final bool toMe = message.recieverId == myId;
// Check that we need to mark message as read
if (isNew && toMe) {
return FutureBuilder<void>(
future: markAsRead(), // markAsRead is a Future function to change your FIELD value in firestore.
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.done) {
return YourMessageWidgetThatWasSeen()
}
return YourMessageWidgetThatWasNotSeen();}); //FutureBuilder ends here.
return MessageBubble(); // or this message is already seen by user and we return message bubble like usually do.
markAsRead() function implementation depends on what structure your database has, for example when your each user has its own collection of messages to store, AND if you have a collections for a dialog preview with last message shown, you will need to create a batch with 4 update operations in it.
Use this flutter library
visibility_detector
Please see the below code, it will help you to implement the read & unread message.
#override
Widget build(BuildContext context) {
return ListView.separated(
itemBuilder: (ctx, index) {
ChatModel chatModel =
ChatModel.fromJson(snapshot.data.docs[index].data());
switch (chatModel.messageType) {
case MessageType.TEXT:
{
return VisibilityDetector(
key: Key(snapshot.data.docs[index].id),
onVisibilityChanged: (VisibilityInfo visibilityInfo) {
var visiblePercentage = visibilityInfo.visibleFraction * 100;
if (visiblePercentage == 100 &&
!chatModel.isSeen &&
chatModel.sender != userController.userModel.value.uid) {
FirebaseFirestore.instance
.collection(FirebaseKeys.chatRoom)
.doc(AppHelper.getChatID(
userController.userModel.value.uid, userModel.uid))
.collection(FirebaseKeys.messages)
.doc(snapshot.data.docs[index].id)
.update({
"isSeen": true,
});
}
},
child:
TextMessage(chatModel, snapshot.data.docs[index].reference),
);
}
case MessageType.GIF:
{
return GifMessage(chatModel, userModel.uid);
}
case MessageType.IMAGE:
{
return ImageMessage(snapshot.data.docs[index].reference,
chatModel, userModel.uid);
}
case MessageType.AUDIO:
{
break;
}
case MessageType.VIDEO:
{
break;
}
case MessageType.PDF:
{
break;
}
case MessageType.FILE:
{
break;
}
case MessageType.OTHER:
{
break;
}
}
return FlutterLogo();
},
shrinkWrap: true,
itemCount: snapshot.data.docs.length,
controller: scrollController,
reverse: true,
physics: ClampingScrollPhysics(),
separatorBuilder: (BuildContext context, int index) {
return Container(
height: 5,
margin: EdgeInsets.only(top: 2, bottom: 2),
);
},
);
}
Generally, it's not correct to keep this mark in the same table.
Because you need to add access rights sender and receiver to change all messages.
Better solution is to create another table something like _metadata and keep this mark there.
I am retrieving data from Firestore in the form of two functions (_onpressed() and _drname()) and called both of them in FutureBuilder.
Function 1 is
Future _onPressed() async {
if (widget.brew.id == currentid.userid()) {
return await db
.collection('Messages')
.doc(widget.brew.id)
.get()
.then((DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists) {
print('${documentSnapshot.data()['Message']}');
String msg = json.encode(documentSnapshot.data()['Message']);
return msg;
} else {
print('Document does not exist on the database');
}
// var a= documentSnapshot.data()['Message'];
});
} else {
return 'No Prescription from doctor yet';
}}
Function 2 is
Future _drname() async {
if (widget.brew.id == currentid.userid()) {
return await db
.collection('Drname')
.doc(widget.brew.id)
.get()
.then((DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists) {
print('${documentSnapshot.data()['name']}');
String msg = json.encode(documentSnapshot.data()['name']);
return msg;
} else {
print('Document does not exist on the database');
}
// var a= documentSnapshot.data()['Message'];
});
} else {
return 'No';
}}
Calling these functions in FutureBuilder like this
Widget _messagePannel() {
return FutureBuilder(
future: Future.wait([_onPressed(),_drname()]),
builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
return Scaffold(
appBar: AppBar(
actions: [
Padding(
padding: const EdgeInsets.only(right: 17.0),
child: TextButton.icon(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Call()),
);
},
icon: Icon(
Icons.video_call,
color: Colors.white,
size: 30.0,
),
label: Text(''),
),
)
],
title: Text(
'Prescrption',
style: TextStyle(fontFamily: 'RussoOne', fontSize: 22.0),
),
backgroundColor: Colors.green[900],
elevation: 0.0,
centerTitle: true,
),
body: Container(
decoration: image,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
color: Colors.black,
child: Center(
child: Padding(
padding: EdgeInsets.fromLTRB(0.0, 4.0, 4.0, 4.0),
child: Wrap(
children: [
Center(
child: Text(
'${snapshot.data[0]} ',
textAlign: TextAlign.left,
style: TextStyle(
fontFamily: 'RussoOne',
color: Colors.white,
letterSpacing: 0.8,
fontSize: 18.0,
backgroundColor: Colors.black),
),
),
Center(
child: Text(
'${snapshot.data[1]} ',
textAlign: TextAlign.left,
style: TextStyle(
fontFamily: 'RussoOne',
color: Colors.white,
letterSpacing: 0.8,
fontSize: 18.0,
backgroundColor: Colors.black),
),
),
],
),
)),
),
),
),
],
),
),
),
);
});}
Getting This error from the Debug Console
The following NoSuchMethodError was thrown building FutureBuilder<List>(dirty, state: _FutureBuilderState<List>#44f46):
The method '[]' was called on null.
Receiver: null
Tried calling:
When using snapshot, the initial value for the data property is null (since Future has no result until you receive the response), so using it straight away as you do it in the code (e.g. snapshot.data[1]) should be avoided.
To cope with that, first of all you should check if the data is not null. For that, snapshot has a dedicated method snapshot.hasData, for instance:
return FutureBuilder(
future: Future.wait([_onPressed(),_drname()]),
builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator(); // E.g. Show loader if there is no data yet
}
return Scaffold(...); // Return the widget you have now
},
);
I am retrieving a list of items by querying on input from textfield in firebase and showing it as list in UI in flutter as shown here
Here is my code-
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app_news/screens/drawer/news_drawer.dart';
import 'package:flutter_app_news/service/search_service/search_service.dart';
class Watchlist extends StatefulWidget {
#override
_WatchlistState createState() => new _WatchlistState();
}
class _WatchlistState extends State<Watchlist> {
var tempSearchStore = [];
var queryResult = [];
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
CollectionReference users = FirebaseFirestore.instance.collection('Users');
initiateSearch(value) {
if (value.length == 0) {
setState(() {
queryResult = [];
tempSearchStore = [];
});
}
if (queryResult.length == 0 && value.length == 1) {
SearchService().searchByName(value).then((QuerySnapshot snapshot) {
for (int i = 0; i < snapshot.docs.length; i++) {
queryResult.add(snapshot.docs[i].data());
setState(() {
tempSearchStore.add(queryResult[i]);
});
}
});
} else {
tempSearchStore = [];
queryResult.forEach((element) {
if (element['name'].toString().startsWith(value)) {
setState(() {
tempSearchStore.add(element);
});
}
});
}
;
if (tempSearchStore.length == 0 && value.length > 1) {
setState(() {});
}
}
#override
Widget build(BuildContext context) {
return new Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
iconTheme: IconThemeData(color: Colors.black),
backgroundColor: Colors.white,
title: Text(
"Finbox",
style: TextStyle(color: Colors.black),
),
),
drawer: Drawer(child: NewsDrawer()),
body: ListView(children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Your WatchList",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: TextField(
onChanged: (val) {
initiateSearch(val);
},
decoration: InputDecoration(
prefixIcon: IconButton(
color: Colors.black,
icon: Icon(Icons.arrow_back),
iconSize: 20.0,
onPressed: () {
Navigator.of(context, rootNavigator: true).pop(context);
},
),
contentPadding: EdgeInsets.only(left: 25.0),
hintText: 'Search by name',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0))),
),
),
SizedBox(height: 10.0),
ListView.builder(
shrinkWrap: true,
itemCount: tempSearchStore.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(tempSearchStore[index]['name']),
onTap: () {
users.doc(_firebaseAuth.currentUser.uid).update({
"subscribeTopic": FieldValue.arrayUnion(
[tempSearchStore[index]['name']])
});
Navigator.pop(context);
},
);
}),
SizedBox(
height: 10,
),
StreamBuilder(
stream: FirebaseFirestore.instance
.collection("Users")
.doc(_firebaseAuth.currentUser.uid)
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<DocumentSnapshot> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Center(
child: CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation<Color>(Colors.black)));
default:
return SingleChildScrollView(
child: GridView.builder(
shrinkWrap: true,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: MediaQuery.of(context)
.size
.width /
(MediaQuery.of(context).size.height / 7),
crossAxisCount: 2),
itemCount: snapshot.data.get('subscribeTopic').length,
itemBuilder: (context, index) {
return GestureDetector(
onLongPress: () {
showAlertDialog(context,
snapshot.data.get('subscribeTopic')[index]);
print(
snapshot.data.get('subscribeTopic')[index]);
},
child: Container(
child: Text(
snapshot.data.get('subscribeTopic')[index],
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500),
),
margin: EdgeInsets.all(15),
decoration: BoxDecoration(
color: Color(0xFF92f7bb),
),
),
);
}),
);
}
})
]));
}
showAlertDialog(BuildContext context, value) {
// set up the buttons
Widget yesButton = ElevatedButton(
child: Text("Yes"),
onPressed: () async {
// await FirebaseMessaging.instance.unsubscribeFromTopic(value);
users.doc(_firebaseAuth.currentUser.uid).update({
"subscribeTopic": FieldValue.arrayRemove([value])
});
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => Watchlist()));
;
},
);
Widget noButton = ElevatedButton(
child: Text("No"),
onPressed: () {
Navigator.of(context).pop();
},
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
title: Text("Finbox"),
content: Text("Do you like to unsubscribe for " + value + " ?"),
actions: [
yesButton,
noButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
}
Here initiateSearch() is function which returns queries in firebase based on input given in textfield and tempSerachStore is list of key value pair. And I am fetching values whose key is "name".
Now the problem I am facing is-
When I write something in textfield and it queries and return a list, list is creating above those green boxes and boxes gets shifted downward as shown in image.
When I tap on one of these items in list or tap on back arrow in textfield , I am poping out to black screen.
What is the output I want-
I want to show this list above these green boxes(whose code is not included here).
When I tap on the item or tap on back arrow , list view should closed.
I will be grateful for help.
Use conditional statement along with Stack. It will work.
Stack(
children: [
// whatever you want to show. Positioned will come on top of it.
data.length == 0 // your search result length
? SizedBox(height: 0)
: Positioned(
top: 0,
width: double.infinity,
child: Container(
// whatever you want to show here
),
]
),
For a good UI experience, it is a good practice to create a separate page for search. On selecting an option, you can bring back the user on your previous page.