Logout with Firebase not working after navigating to a particular screen - firebase

Logout works fine from the home screen and even when navigating to other screens and then returning to the home screen to logout, however, when starting the assessment from the home screen which takes you to 'assessment_list' and you return to the home screen, logout doesn't work. How would I fix this?
Home Screen
actions: [
...
items: [
DropdownMenuItem(
child: Container(
child: Row(
children: [
const Icon(Icons.exit_to_app),
const Text('Logout'),
const SizedBox(width: 8),
],
),
),
value: 'logout',
),
],
onChanged: (itemIdentifier) {
if (itemIdentifier == 'logout') {
FirebaseAuth.instance.signOut();
}
...
RaisedButton(
child: Text(
'Start Assessment'
),
onPressed: () {
navigateToAssessmentList(context);
},
),
...
Future navigateToAssessmentList(context) async {
Navigator.push(
context, MaterialPageRoute(builder: (context) => AssessmentList()));
}
assessment_list
child: RaisedButton(
padding: EdgeInsets.all(10),
color: const Color(0xfff4f4f4),
child: Text(
'Back To Home',
),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => BottomNavBarController()));
}),

You are pushing the same page again in the stack. Please replace the following line
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => BottomNavBarController()));
with this
Navigator.pop(context)

Related

UI not updated Flutter Web

I have a Table reading data from Firestore, using StreamBuilder. I have a button Add Element below the table that when clicked opens a pop-up form. After the user fills the form and clicks the button, data is stored in Firestore, the Dialog form is closed and the user is redirected to the table. When I use only text form fields in my form, the table is updated with the new data that the user just pushed in Firestore. The problem started to occurs when I added an Upload Picture Form, which uploads the picture in Firebase Storage and pushes the download URL as a field inside the other information of the form. I fill the form and the Table doesn't update. The project is in Flutter Web so I am using image_picker_web for the upload process and the Image file is MediaInfo type. As I said it started to happen only when I added the upload picture form along with other TextFormFields.
// Upload Picture Field
InkWell(
onTap: () async {
final MediaInfo _image =
await ImagePickerWeb.getImageInfo;
setState(() {
image = _image;
});
},
child: Container(
child: Center(
child: Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Icon(
CupertinoIcons.cloud_upload,
color: Colors.grey[600],
),
const SizedBox(
width: 5,
),
Text(
'Upload the invoice picture',
style: TextStyle(
color: Colors.grey[600],
),
),
],
),
),
),
),
//Create Invoice Button
MaterialButton(
onPressed: () async {
Invoice invoice = Invoice(
_controllerInvoiceNumber.text,
_controllerLocation.text,
invoiceDate,
_controllerAmount.text,
);
Database().addNewInvoice(
invoice,
_userId!,
image!,
);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const HomePage(),
),
);
}
},
child: const Text(
'Create',
),
),
//Table
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('Invoices')
.snapshots(),
builder: (context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
}
return Column(
children: [
SizedBox(
child: PlutoGrid(
columns: editableColumns,
rows: _createRows(snapshot.data),
),
),
Padding(
padding: const EdgeInsets.all(10),
child: Center(
child: MaterialButton(
child: const Text(
'Add Invoice',
style: TextStyle(color: Colors.white),
),
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return const AddInvoiceForm();
},
);
},
),
),
),
],
);
},
),

How to click on an image to display the details of that image (that data is taken from firebase)

How can I know which event I clicked on? How to click on an image to display the details of that image (that data is taken from firebase). I can't find a solution to this problem, please help!
Widget _allUsers(BuildContext context) {
return StreamBuilder <List<MatHangSnapshot>>(
stream: getAllMatHangFromFirebase(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(child: CircularProgressIndicator(),);
else {
return GridView.builder(
itemCount: snapshot.data.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemBuilder: (context, index) {
return Card(
child: GridTile(
child: FlatButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ChiTietNongSan()),
);
},
padding: EdgeInsets.all(0.0),
child: Column(
children: [
Image.network(snapshot.data[index].mh.image, width: 150, height: 150,),
],
),
),
footer: Column(
children: [
Center(
child: Text(snapshot.data[index].mh.tenMH, style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold),),
),
Center(
child: Text("Giá: ${snapshot.data[index].mh.gia.toString()}/kg",style: TextStyle(fontSize: 15, color: Colors.red),),
)
],
)
accept the image via the constructor of ChiTietNongSan class then make your onPressed look like this
onPressed: () {
//change this to your actual image
var image = snapshot.data[index]["image"];
Navigator.push(context,
MaterialPageRoute(builder: (context) => ChiTietNongSan(image)),
);
},
You can get the image in the FlatButton's onPressed method, the same way you're displaying it in the Image.network widget by using the code below:
snapshot.data[index].mh.image
And you can use it in your onPressed like this:
FlatButton(
onPressed: () {
print(snapshot.data[index].mh.image);
Navigator.push(context, MaterialPageRoute(builder: (context) => ChiTietNongSan()),);
},
...
)
The important thing with knowing which exact image you clicked on is the index and you can use that to get any information you need from the MatHangSnapshot class.

NoSuchMethodError. The getter 'weekday' was called on null. Table_Calendar Flutter

I'm stuck with the table calendar.
In Android Studio I get following error:
The following NoSuchMethodError was thrown building StreamBuilder<List<AppEvent>>(dirty, state: _StreamBuilderBaseState<List<AppEvent>, AsyncSnapshot<List<AppEvent>>>#c5581):
The getter 'weekday' was called on null.
Receiver: null
Tried calling: weekday
This is my code: If necessarily I can post more code such the classes.
The other code works perfekt. even in the red issuescreen in the app I can trigger the floated button and add an event. But I cant see the calendar anymore cause the red issuescreen.
import 'package:app_tennis_sv_schwaig/kalender/add_event.dart';
import 'package:app_tennis_sv_schwaig/kalender/event_details.dart';
import 'package:app_tennis_sv_schwaig/kalender/event_firestore_service.dart';
import 'package:app_tennis_sv_schwaig/kalender/app_event.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:table_calendar/table_calendar.dart';
class TennisKalender extends StatefulWidget {
#override
_TennisKalenderState createState() => _TennisKalenderState();
}
class _TennisKalenderState extends State<TennisKalender> {
CalendarController _calendarController = CalendarController();
Map<DateTime, List<AppEvent>> _groupedEvents;
_groupEvents(List<AppEvent> events) {
_groupedEvents = {};
events.forEach((event) {
DateTime date =
DateTime.utc(event.date.year, event.date.month, event.date.day, 12);
if (_groupedEvents[date] == null) _groupedEvents[date] = [];
_groupedEvents[date].add(event);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.orange,
appBar: AppBar(
backgroundColor: Colors.red,
title: Text("Tenniskalender"),
actions: <Widget>[
IconButton(
icon: Icon(Icons.person),
onPressed: (null),
)
],
),
body: SingleChildScrollView(
child: StreamBuilder(
stream: eventDBS.streamList(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
final events = snapshot.data;
_groupEvents(events);
DateTime selectedDate = _calendarController.selectedDay;
final _selectedEvents = _groupedEvents[selectedDate] ?? [];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Card(
clipBehavior: Clip.antiAlias,
margin: const EdgeInsets.all(8.0),
child: TableCalendar(
calendarController: _calendarController,
events: _groupedEvents,
onDaySelected: (date, events, holidays) {
setState(() {});
},
startingDayOfWeek: StartingDayOfWeek.monday,
headerStyle: HeaderStyle(
decoration: BoxDecoration(
color: Colors.red,
),
headerMargin: const EdgeInsets.only(bottom: 8.0),
),
),
),
Padding(
padding: const EdgeInsets.only(left: 12.0, top: 8.0),
child: Text(
DateFormat('EEEE, dd MMMM, yyyy').format(selectedDate),
style: Theme.of(context).textTheme.headline6,
),
),
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: _selectedEvents.length,
itemBuilder: (BuildContext context, int index) {
AppEvent event = _selectedEvents[index];
return ListTile(
title: Text(event.title),
subtitle: Text(DateFormat("EEEE, dd MMMM, yyyy")
.format(event.date)),
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => EventDetails(
event: event,
)),
);
},
trailing: IconButton(
icon: Icon(Icons.edit),
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => AddEventPage(
event: event,
)));
},
));
},
),
],
);
}
return CircularProgressIndicator();
},
),
),
floatingActionButton: FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.grey[900],
),
backgroundColor: Colors.yellow,
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => AddEventPage(
selectedDate: _calendarController.selectedDay,
),
),
);
}),
);
}
}
I dont get it where the weekday is written null.
Can you please help? Thanks a lot!
I solved it. In fact others have a similar issue here's my solution.
The DateFormat in the ListTile from the ListView.builder was the Problem. Don't know why but I deleted it, cause don't needed the view in the app anyway.
Errorcommand:
subtitle: Text(DateFormat("EEEE, dd MMMM, yyyy").format(event.date)),

Navigator change page on async button press

Very new to Flutter. How would I push a new route predicated on a condition invoked by a button press? (asynchronous sign in call).
This sort of thing: if signIn (async) = success -> Navigator.push
Cheers
Widget buildButtons() {
return new Container(
child: new Column(
children: <Widget>[
new MaterialButton(
minWidth: MediaQuery.of(context).size.width - 30, //FULL WIDTH - 30
color: Style.palette3,
padding: EdgeInsets.all(Style.padding1),
child: new Text('Sign in',
style: Style.signInBtn
),
onPressed: () {
if (LoginControl.signIn()) Navigator.push(context, MaterialPageRoute(builder: (context) => ArmDisarm()));
},
),
new FlatButton(
child: Padding(
padding: Style.paddingCreateAcc,
child: new Text(
'Create an account',
style: Style.fontSize1
),
),
),
],
),
);
}
It's better to show us the code of LoginControl.signIn().
Anyway if signIn() is a Future, then you to use async await
...
onPressed: () async {
if (await LoginControl.signIn()) {
Navigator.push(context, MaterialPageRoute(builder: (context) => ArmDisarm()));
}
},
...
Make sure that signIn() method returns true if the user is successfully signed in.

how can i have an logout option in my flutter application?

i have developed an admin app in that i have login page that directs to my dashboard ther i have option for log out but i'm not able to do it.
Here's my code:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Row(
children: <Widget>[
Expanded(
child: FlatButton.icon(
onPressed: () {
setState(() => _selectedPage = Page.dashboard);
},
icon: Icon(
Icons.dashboard,
color: _selectedPage == Page.dashboard
? active
: notActive,
),
label: Text('Dashboard'))),
Expanded(
child: FlatButton.icon(
onPressed: () {
setState(() => _selectedPage = Page.manage);
},
icon: Icon(
Icons.sort,
color:
_selectedPage == Page.manage ? active : notActive,
),
label: Text('Manage'))),
],
),
elevation: 0.0,
backgroundColor: Colors.white,
),
body: _loadScreen());
}
Widget _loadScreen() {
switch (_selectedPage) {
case Page.dashboard:
return FutureBuilder(
future: getUsersCount(),
builder: (BuildContext context, AsyncSnapshot<String> text) {
print(text);
if(text== "-1"){
return CircularProgressIndicator();
} else {
return Column(
children: <Widget>[
ListTile(
subtitle: Text('Admin View', textAlign: TextAlign.center,
style: TextStyle(fontSize: 29.0,
color: Colors.indigo,
fontWeight: FontWeight.bold),),
),
Expanded(child: GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,),
children: <Widget>[
Padding(padding: const EdgeInsets.all(18.0),
child: Card(child: ListTile(
title: FlatButton.icon(
onPressed: null,
icon: Icon(
Icons.people, color: Colors.black,),
label: Text("Users", style: TextStyle(
fontSize: 9, color: Colors.indigo),)),
subtitle: Text(text.data != null ? text.data : '',
textAlign: TextAlign.center,
style: TextStyle(color: active, fontSize: 50.0),
)),
),
),
],
),
),
],
);
}
});
break;
case Page.manage:
return ListView(
children: <Widget>[
ListTile(
leading: Icon(Icons.lock,color: Colors.black,),
title: Text("Logout",style: TextStyle(color: Colors.indigo),),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context)=> AdminLogin()));
// _brandAlert();
},
),
Divider(),
],
);
break;
default:
return Container();
}
}
void _categoryAlert() {
var alert = new AlertDialog(
content: Form(
key: _categoryFormKey,
child: TextFormField(
controller: categoryController,
validator: (value){
if(value.isEmpty){
return 'category cannot be empty';
}
return null;
},
decoration: InputDecoration(
hintText: "add Promocode",
),
),
),
actions: <Widget>[
FlatButton(onPressed: (){
if(categoryController.text != null){
_categoryService.createCategory(categoryController.text);
}
Fluttertoast.showToast(msg: 'Promocode changed');
Navigator.pop(context);
}, child: Text('ADD')),
FlatButton(onPressed: (){
Navigator.pop(context);
}, child: Text('CANCEL')),
],
);
showDialog(context: context, builder: (_) => alert);
}
}
i want the admin dashboard to be logged out and then switch to my login page again.
replace this line
Navigator.push(context, MaterialPageRoute(builder: (context)=> AdminLogin()));
with
final route = MaterialPageRoute(builder: (BuildContext context) => AdminLogin());
Navigator.of(this.context).pushAndRemoveUntil(route, (Route<dynamic> route) => false);
U need pushReplacementNamed rather then only push,
Navigator.pushReplacementNamed(context, '/Login');
or
navigator.pushReplacement(
MaterialPageRoute(builder: (BuildContext context) => Login()));
Use-case : pushReplacementNamed
When the user has logged in successfully, and are now on the DashboardScreen perhaps, then you don’t want the user to go back to LoginScreen in any case. So login route should be completely replaced by the dashboard route. Another example would be going to HomeScreen from SplashScreen. It should only display once and the user should not be able to go back to it from HomeScreen again. In such cases, since we are going to a completely new screen, we may want to use this method for its enter animation property. Read more on this

Resources