How do I fix dart flutter scaffoldKey problem? - flutter

I will describe my coding problem.
Well I have created Login/signUp .dart files(pages) but while debugging I got this error...
The method 'showSnackBar' isn`t defined for the type 'ScaffoldState'.
This error message appears everywhere in .dart code where I have this coding line...
`
scaffoldKey.currentState.showSnackBar(snackbar);
`
Here below is full code of my "login_page.dart" file...
`
class LoginPage extends StatefulWidget {
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();
void showSnackBar(String title) {
final snackbar = SnackBar(
content: Text(
title,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 15),
),
);
scaffoldKey.currentState.showSnackBar(snackbar);
}
var emailIdController = TextEditingController();
var passwordController = TextEditingController();
Widget _buildLogin() {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 30),
child: Column(
children: [
InputTextField(
controller: emailIdController,
label: 'Email-Id',
icon: Icon(Icons.email_outlined),
),
InputTextField(
controller: passwordController,
label: 'Password',
icon: Icon(Icons.lock),
),
SizedBox(
height: 50,
),
GestureDetector(
onTap: () async {
// network connectivity
var connectivityResult = await Connectivity().checkConnectivity();
if (connectivityResult != ConnectivityResult.mobile &&
connectivityResult != ConnectivityResult.wifi) {
showSnackBar('No Internet connectivity');
return;
}
if (!emailIdController.text.contains('#')) {
showSnackBar('Please provide a valid email address');
}
if (passwordController.text.length < 6) {
showSnackBar('Please provide a password of length more than 6');
}
BuildContext dialogContext;
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
dialogContext = context;
return ProgressDialog(
status: 'Logging you in...',
);
},
);
context
.read<AuthenticationService>()
.signIn(
email: emailIdController.text.trim(),
password: passwordController.text.trim(),
)
.then((value) => Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return HomePage();
}),
));
Navigator.pop(dialogContext);
},
child: CustomButton(
text: 'Login',
),
),
Text("\nDon't have any account?"),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return SignUpPage();
}),
);
},
child: Text(
'SignUp here',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12),
),
),
SizedBox(
height: 20,
),
],
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
body: SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Padding(
padding: EdgeInsets.only(top: 130),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
'hopOn',
style: TextStyle(
fontSize: 60,
letterSpacing: 2,
fontWeight: FontWeight.bold,
fontFamily: 'MuseoModerno',
// color: Colors.white,
),
),
SizedBox(height: 80),
Padding(
padding: EdgeInsets.symmetric(horizontal: 30),
child: Column(
children: [
InputTextField(
controller: emailIdController,
label: 'Email-Id',
obscure: false,
icon: Icon(Icons.email_outlined),
),
InputTextField(
controller: passwordController,
label: 'Password',
obscure: true,
icon: Icon(Icons.lock),
),
SizedBox(
height: 30,
),
GestureDetector(
onTap: () async {
// network connectivity
var connectivityResult =
await Connectivity().checkConnectivity();
if (connectivityResult != ConnectivityResult.mobile &&
connectivityResult != ConnectivityResult.wifi) {
showSnackBar('No Internet connectivity');
return;
}
if (!emailIdController.text.contains('#')) {
showSnackBar(
'Please provide a valid email address');
}
if (passwordController.text.length < 6) {
showSnackBar(
'Please provide a password of length more than 6');
}
BuildContext dialogContext;
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
dialogContext = context;
return ProgressDialog(
status: 'Logging you in...',
);
},
);
context
.read<AuthenticationService>()
.signIn(
email: emailIdController.text.trim(),
password: passwordController.text.trim(),
)
.then((value) => Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return HomePage();
}),
));
Navigator.pop(dialogContext);
},
child: CustomButton(
text: 'Login',
),
),
SizedBox(
height: 20,
),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return SignUpPage();
}),
);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Don't have any account?\t",
style: TextStyle(fontSize: 10),
),
Text(
'SignUp here',
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 12),
),
],
),
),
SizedBox(
height: 20,
),
],
),
),
],
),
),
),
),
);
}
}
`
The problem from whole code appears in this class...
`
void showSnackBar(String title) {
final snackbar = SnackBar(
content: Text(
title,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 15),
),
);
scaffoldKey.currentState.showSnackBar(snackbar); // <=== here is problem, this line have error message --> The method 'showSnackBar' isn`t defined for the type 'ScaffoldState'.
}
`
Any help is appreciated.
Thank you!
I would like to fix that "snackBar" error problem.
I tryed several hours to fix it by myself but without succees.

Flutter uses below method to display the snackbar as per flutter.dev
ScaffoldMessenger.of(context).showSnackBar(snackBar);

I found a solution idea that other user named "Rohan" gave to me.
I changed problematic code line...
scaffoldKey.currentState.showSnackBar(snackbar);
to first solution (which still didn't worked,, appeared error "Undefined name: 'snackbar'")...
ScaffoldMessenger.of(context).showSnackBar(snackBar);
Didn`t worked, but then I found a solution from previous sample solution. This is general and working Solution for my problem...
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: snackbar));
This solution will help you, if you found the same or similar issue with "showSnackBar".

Related

flutter_bloc is not resetting its Cubit Model values when we try to push the same screen more than one time

Here is my main.dart code,
void main() {
// Bloc.observer = AppBlocObserver();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<SignInCubit>(
create: (BuildContext context) => SignInCubit(),
),
BlocProvider<SignUpCubit>(
create: (BuildContext context) => SignUpCubit(),
),
],
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return OrientationBuilder(
builder: (BuildContext context, Orientation orientation) {
//sizeConfiguration
SizeConfig().init(constraints, orientation);
return MaterialApp(
title: 'Flutter Demo',
theme: lightThemeData(context),
darkTheme: darkThemeData(context),
// themeMode: _themeMode,
scaffoldMessengerKey: Messenger.rootScaffoldMessengerKey,
navigatorKey: CustomRoutes.navigatorKey,
home: const SplashPage(),
initialRoute: SplashPage.id,
routes: <String, WidgetBuilder> {
SplashPage.id:(BuildContext context) => const SplashPage(),
SignInPage.id: (BuildContext context) => const SignInPage(),
SignUpPage.id: (BuildContext context) => const SignUpPage(),
},
);
});
}),
);
}
Here is the code on SignIn screen,
class SignInPage extends StatefulWidget {
const SignInPage({super.key});
static const String id = 'SignInPage';
#override
State<SignInPage> createState() => _SignInPageState();
}
class _SignInPageState extends State<SignInPage> {
final dynamic _formKey = GlobalKey<FormState>();
final TextEditingController _passwordController = TextEditingController();
#override
void initState() {
createFocusNodeListeners();
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
_passwordFocus.addListener(_passwordListener);
});
super.initState();
}
#override
Widget build(BuildContext context) {
final CTTheme cTTheme = Theme.of(context).extension<CTTheme>()!;
//https://medium.com/codex/flutter-bloc-an-introduction-with-cubit-7eae1e740fd0
final SignInCubitModel state = context.watch<SignInCubit>().state;
return Scaffold(
body: CustomPaint(
painter:
LoginCustomPaint(customPaintColor: cTTheme.customPaintCircleColor1),
child: GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24), // common padding
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const SizedBox(
height: 98,
),
Text(
AppStrings.welcomeTo, // heading 3
style: cTTheme.heading3,
),
const SizedBox(
height: 16,
),
RichText(
text: TextSpan(
text: AppStrings.m,
style: cTTheme.heading1, // heading1 with pink color
children: <TextSpan>[
TextSpan(
text: AppStrings.onteFiore,
style: cTTheme.heading2, //heading2 with pink color
),
TextSpan(
text: '\n${AppStrings.c}', style: cTTheme.heading1),
TextSpan(
text: AppStrings.linical, style: cTTheme.heading2),
TextSpan(
text: ' ${AppStrings.t}', style: cTTheme.heading1),
TextSpan(
text: AppStrings.rials, style: cTTheme.heading2),
],
),
),
const SizedBox(
height: 16,
),
Text(
AppStrings.findOutClinicalTrailAndStudies,
style: cTTheme.subtitle3, // subtitle 1
),
SizedBox(
height: SizeConfig.heightMultiplier! * 19.8,
),
TextFormField(
autofocus: false,
style:cTTheme.menuItemTextStyle,
controller: _passwordController,
autovalidateMode: state.passwordValidation
? AutovalidateMode.onUserInteraction
: AutovalidateMode.disabled,
obscureText: !state.signInPasswordVisibility,
// obscuringCharacter: '*',
focusNode: _passwordFocus,
decoration: kTextFieldDecoration2(context).copyWith(
labelText: AppStrings.password,
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: state.isInvalidPassWord
? state.passWordTextFormFieldColor
: cTTheme.dividerColor!)),
prefixIcon: Padding(
padding: const EdgeInsetsDirectional.only(end: 16.0),
child: Image.asset(// constants
AppIconsPath.padLockIcon),
),
suffixIcon: InkWell(
onTap: () {
context
.read<SignInCubit>()
.changeSignINPassowrdVisibilty(
state.signInPasswordVisibility
? ChangePasswordVisibilityEnum.invisible
: ChangePasswordVisibilityEnum.visible);
},
child: state.signInPasswordVisibility
? Image.asset(AppIconsPath.eyeIcon)
: Image.asset(AppIconsPath.privacyIcon),
),
),
onTap: () => context
.read<SignInCubit>()
.changePasswordTextFormFieldColor(
color: cTTheme.dividerColor!,
isInvalidPassWord: false),
onChanged: (String? value) {
_debouncer.run(() {
checkControllerValues();
});
},
onEditingComplete: () {
if (Validators.validateSignInPassword(
_passwordController.text) !=
null) {
context
.read<SignInCubit>()
.enableValidatorForPasswordTextField();
}
},
validator: (String? value) =>
Validators.validateSignInPassword(value!),
),
errorMessage(state.isInvalidPassWord, 'Password Is Incorrect'),
const SizedBox(
height: 14,
),
Align(
alignment: Alignment.bottomRight,
child: InkWell(
onTap: () async {
final bool isConnocted = await checkConnectivity();
if (isConnocted) {
CustomRoutes.push(
screen: const ForgotPasswordPage());
return;
}
CustomRoutes.push(
screen: InternetErrorScreen(
onPressed: () {
ConnectivityManager.internetChecker()
.then((bool retry) {
if (retry) {
CustomRoutes.back();
}
});
},
),
);
},
child: Text(
AppStrings.forgotPassword,
style: cTTheme.description1,
))),
const SizedBox(
height: 48,
),
PrimaryButton(
onPressed: state.isSignInButtonDissabled
? null
: () {
FocusManager.instance.primaryFocus?.unfocus();
if (_formKey.currentState!.validate()) {
context.read<SignInCubit>().onSignInSubmit(
_emailOrPhoneController.text,
_passwordController.text);
}
},
text: AppStrings.signIn.toUpperCase(),
isLoadingVisible: state.isLoading,
),
const SizedBox(
height: 16,
),
InkWell(
onTap: () async {
final bool isConnocted = await checkConnectivity();
if (isConnocted) {
Navigator.pushNamed(context, SignUpPage.id);
// CustomRoutes.pushreplace(screen: const SignUpPage());
return;
}
CustomRoutes.push(
screen: InternetErrorScreen(onPressed: () {
ConnectivityManager.internetChecker()
.then((bool retry) {
if (retry) {
CustomRoutes.back();
}
});
}));
},
child: Center(
child: RichText(
text: TextSpan(
text: AppStrings.dontHaveAnAccount,
style: cTTheme.subtitle2,
children: <TextSpan>[
TextSpan(
text: ' ${AppStrings.signUp}',
style: cTTheme.iconButtonTextStyle),
],
),
),
),
),
const SizedBox(
height: 66,
),
Center(
child: Text(
AppStrings.byLoggingInYouAgreeToOur,
style: cTTheme.noteTextStyle1,
)),
const SizedBox(
height: 6,
),
Center(
child: InkWell(
onTap: () => CustomRoutes.push(
screen: InternetErrorScreen(onPressed: () {
ConnectivityManager.internetChecker().then((bool value) {
if (value) {
CustomRoutes.back();
}
});
})),
child: Text(
AppStrings.termsAndpolicies,
style: cTTheme.noteTextStyle2,
),
)),
const SizedBox(
height: 20,
),
],
),
),
),
),
),
));
}
I am switching(show/hide) eye icon on the password textfield to show and hide the eye image using "changeSignINPassowrdVisibilty" function from cubit file. Here is the Cubit file code,
class SignInCubit extends Cubit<SignInCubitModel> {
SignInCubit()
: super(
SignInCubitModel()); // here inside SignInCubit class, all the fields are already initialized
final CTTheme cTTheme =
Theme.of(CustomRoutes.navigatorKey.currentContext!).extension<CTTheme>()!;
void changeSignINPassowrdVisibilty(ChangePasswordVisibilityEnum newState) {
emit(state.copyWith(
signInPasswordVisibility:
newState == ChangePasswordVisibilityEnum.visible));
}
}
Here is the code from SignInCubitModel class,
class SignInCubitModel {
SignInCubitModel({
this.signInPasswordVisibility = false,
});
bool signInPasswordVisibility;
SignInCubitModel copyWith({
bool? signInPasswordVisibility,
}) {
return SignInCubitModel(
signInPasswordVisibility:
signInPasswordVisibility ?? this.signInPasswordVisibility,
);
}
}
Initially signInPasswordVisibility field value is false. When user try to switch visibility of the password , signInPasswordVisibility will change its value to true or false.
Here is my problem,
1.I am enabling signInPasswordVisibility to true on SignIn screen by clicking eye icon. Please note now signInPasswordVisibility value is true.
And
2.I am pushing to Signup screen when they click signup button from SignIn screen.
And
3.I am pushing to SignIn screen again when they click SignIn button from signup screen.
But this time signInPasswordVisibility value in SignIn screen still remains true. Its supposed to be false since I am pushing to this screen again. It has to reset the all SignIn screen state values when I push to SignIn screen. But Its not happening.
Signin screen still keeps old state values even if I push to the Signin screen multiple time.
Is there any problem with the way I implemented flutter_bloc? OR Is there any solution to reset the state values every time we push the SignIn screen?

Data not updating in DB Sqflite Flutter

The task text in edit_todo_screen is not updated. I'm using the same code as in item_tasks, where I change the status of the task to move between "Done" and "Archived" - everything works well here. I tried to change only the status in edit_todo_screen, but it does not change, although the code is identical to the code in item_tasks. Perhaps the problem is that I'm not passing the parameters correctly to edit_todo_screen. I need to be able to change the status of the task and the text of the task itself in edit_todo_screen. Attached below is a screenshot of the error that occurs when clicking the button in edit_todo_screen
Tell me, please, what could be my mistake?
cubit_db
class AppCubit extends Cubit<AppStates> {
AppCubit() : super(AppInitialState());
static AppCubit get(context) => BlocProvider.of(context);
void updateDatabase(String status, int id) async {
database!.rawUpdate(
'UPDATE tasks SET status = ? WHERE id = ?', [status, id]).then((value) {
getDataBase(database);
emit(AppUpdateDatabaseState());
});
}
void createDatabase() {
openDatabase(
'todo.db',
version: 1,
onCreate: (database, version) {
database
.execute(
'CREATE TABLE tasks (id INTEGER PRIMARY KEY, title TEXT, status TEXT)')
.then((value) => print('Table Created'))
.catchError((error) {
print('Error When Creating Table ${error.toString()}');
});
},
onOpen: (database) {
getDataBase(database);
print('database opened');
},
).then((value) {
database = value;
emit(AppCreateDatabaseState());
});
}
inserToDatabase({required String title}) async {
await database!.transaction((txn) async {
txn
.rawInsert(
'INSERT INTO tasks (title, status) VALUES ("$title","New")')
.then((value) {
getDataBase(database);
print('$value Inserted Successfully');
emit(AppInsertDatabaseState());
}).catchError((error) {
print('Error When inserting Table ${error.toString()}');
});
});
}
new_tasks_list
class NewTasksScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return BlocConsumer<AppCubit, AppStates>(
listener: (context, state) {},
builder: (context, state) {
var tasks = AppCubit.get(context).newTasks;
return SingleChildScrollView(
child: Column(children: [
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: tasks.length,
itemBuilder: (context, index) => TaskItem(tasks: tasks[index]),
),
]),
);
},
);
tasks_item
class TaskItem extends StatelessWidget {
Map? tasks;
TaskItem({this.tasks});
#override
Widget build(BuildContext context) {
return Card(
key: Key(tasks!['title']),
shadowColor: Colors.blueGrey,
margin: const EdgeInsets.only(left: 15, right: 15, top: 8),
color: Colors.black,
shape: RoundedRectangleBorder(
side: BorderSide(color: Colors.grey.shade800, width: 0.5),
borderRadius: BorderRadius.circular(10),
),
borderOnForeground: false,
child: ListTile(
title: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(
// '${state.loadedUser[index].description}',
tasks!['title'],
style: const TextStyle(
fontSize: 21.0,
// fontWeight: FontWeight.bold,
),
),
// Text(
// tasks!['status'],
// style: const TextStyle(fontSize: 21.0),
// ),
]),
trailing: IconButton(
tooltip: 'Archive Todo',
highlightColor: Colors.red,
onPressed: () {
AppCubit.get(context).updateDatabase('Archive', tasks!['id']);
},
icon: const Icon(
Icons.archive,
color: Colors.white,
),
),
leading: IconButton(
tooltip: 'Done Todo',
highlightColor: Colors.green,
onPressed: () {
AppCubit.get(context).updateDatabase('Done', tasks!['id']);
},
icon: const Icon(
Icons.check,
color: Colors.white,
),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditTodoScreen(
title: tasks!['title'],
id: tasks!['id'],
),
),
);
},
),
);
}
}
edit_todo_screen
class EditTodoScreen extends StatelessWidget {
// Map? tasks;
String title;
int id;
EditTodoScreen({Key? key, required this.title, required this.id})
: super(key: key);
final _controller = TextEditingController();
#override
Widget build(BuildContext context) {
_controller.text = title;
return BlocConsumer<AppCubit, AppStates>(
listener: (context, state) {},
builder: (context, state) {
return Scaffold(
appBar: AppBar(
title: const Text(
'Edit Todo',
style: TextStyle(fontSize: 20.0),
),
),
body: _body(context),
);
});
}
Widget _body(context) {
return Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
TextFormField(
controller: _controller,
autocorrect: true,
maxLines: 2,
decoration: const InputDecoration(hintText: 'Enter todo message'),
),
const SizedBox(
height: 10.0,
),
// ElevatedButton(
// // style:,
// onPressed: () {
// AppCubit.get(context).updateDatabase('Done', id);
// },
// child: Text(
// 'Update Data',
// style: TextStyle(color: Colors.amber.shade700),
// ),
// ),
InkWell(
onTap: () {
AppCubit.get(context).updateDatabase('Done', id);
Navigator.pop(context);
},
child: _updateBtn(context),
)
],
),
);
}
Widget _updateBtn(context) {
return Container(
width: MediaQuery.of(context).size.width,
height: 50.0,
decoration: BoxDecoration(
color: Colors.black, borderRadius: BorderRadius.circular(10.0)),
child: Center(
child: Text(
'Update Todo',
style: TextStyle(
fontSize: 17.0,
color: Colors.amber.shade700,
fontWeight: FontWeight.bold),
),
),
);
}
}
I think your problem has to do with the fact that database is not set in the second case. The code fails because you try to access a null value that then is checked with the "!" operator. Look where you set the database and check if that code is called in both code flows.
edit:
I think this line in edit todo screen is your problem: AppCubit.get(context).updateDatabase('Done', id);. If I am not mistaken AppCubit.get(context) returns null. The easiest way to check if I am right would be to replace it with the following:
final appCubit = AppCubit.get(context);
print('$appCubit');
appCubit.updateDatabase('Done', id);
If I am right, you should see "null" in your terminal.
What I think happens is, that the app cubit is not provided in the context anymore, because you pushed the todo screen as a new screen on the navigator. With that, the context that is provided is that of the navigator (or probably the material app in your case) which is above the point where you provide the AppCubit.
I am kind of guessing though, because I only see half of your code. I hope it helps nevertheless. :)

Get Document ID of Firestore Document (Flutter)

enter image description here
Trying already for a couple of days to get document id of a document in Firestore from my Flutter app.
what I want is to update or delete document, but have to identify it first by his id.
I have that ID with other values like name, address, etc.., when I open Firestore.
Now I am trying to understand how to get document id into a variable, which I then use in my function to delete or update the document.
getDocIndex() {
var documentID = Firestore.instance
.collection('Requests')
.document(widget.data['Document ID'].toString())
.get();
print(documentID);
}
I understand that widget in a function is not usable. Maybe something with snapshot.data.... but its also marked as red.
This is my function which then should work:
deleteDocument(){
Firestore.instance.collection('Requests').document(documentID).delete();
}
enter image description here
enter image description here
If you know the values inside the document, you can use a where query to find all documents that have those parameters.
Firestore.instance.collection('requests').where('Document ID', isEqualTo: "ID")
.snapshots().listen(
(data) => print('grower ${data.documents[0]['name']}')
);
However, if you already have access to the document's data locally, you can pull the reference path from the document snapshot if you have stored it locally. It is only an issue of recovering that data from within your app at that point.
Thank you all! I've got it!
return ListTile(
title: Text(
'${snapshot.data[index].data['Name']}',
style: GoogleFonts.lexendDeca(),
),
subtitle: Text(
'${snapshot.data[index].data['Anfrage vom']}',
style: GoogleFonts.lexendDeca(),
),
onTap: () {
navigateToDetail(snapshot.data[index]);
keyID = snapshot.data[index].data['Document ID'];
print(keyID.toString());
Below I get in keyID the Document ID from field in a document. After that I can use the delete function with ID reference.
Firestore.instance.collection('Requests').document(keyID).delete();
getDocIndex() {
var document = Firestore.instance
.collection('Requests')
.document(widget.data['Document ID'].toString())
.get();
print(document.id);
}
getDocIndex() async {
var document = await Firestore.instance
.collection('Requests')
.document(widget.data['Document ID'].toString())
.get();
print(document.id);
}
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:kuechenrechner/card_widget.dart';
import 'package:kuechenrechner/gmaps.dart';
import 'package:geocoder/geocoder.dart';
import 'adminslogin.dart';
//final documentsRef = Firestore.instance.collection('Requests');
class Admins extends StatefulWidget {
#override
_AdminsState createState() => _AdminsState();
}
class _AdminsState extends State<Admins> {
/*geoConvert() async {
// Geocoding for Address
// final query = "1600 Amphiteatre Parkway, Mountain View";
var addresses = await Geocoder.local.findAddressesFromQuery(query);
var first = addresses.first;
print("${first.featureName} : ${first.coordinates}");
}
*/
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return AdminsLogin();
}));
}),
title: Text(
'Anfragen',
style: GoogleFonts.lexendDeca(),
),
centerTitle: true,
actions: [
IconButton(
icon: Icon(Icons.refresh),
onPressed: () {
setState(() {});
})
],
),
body: AdminsList(),
);
}
}
Future getPosts() async {
var firestore = Firestore.instance;
QuerySnapshot qn = await firestore
.collection("Requests")
.orderBy('Anfrage vom')
.getDocuments();
return qn.documents;
}
//Abfrage DocumentID
getDocIndex() async {
/* var documentID = Firestore.instance
.collection('Requests')
.document(widget.data['Document ID'].toString())
.get();
print(documentID);
*/
var document = await Firestore.instance
.collection('Requests')
.document(widget.data['Document ID'].toString())
.get();
print(document.id);
}
class AdminsList extends StatefulWidget {
#override
_AdminsListState createState() => _AdminsListState();
}
class _AdminsListState extends State<AdminsList> {
navigateToDetail(DocumentSnapshot post) {
Navigator.push(context,
MaterialPageRoute(builder: (context) => AdminsDetails(post: post)));
}
#override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder(
future: getPosts(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: Text('Loading...'),
);
} else {
return ListView.separated(
reverse: true,
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (_, index) {
return ListTile(
title: Text(
'${snapshot.data[index].data['Name']}',
style: GoogleFonts.lexendDeca(),
),
subtitle: Text(
'${snapshot.data[index].data['Anfrage vom']}',
style: GoogleFonts.lexendDeca(),
),
onTap: () => navigateToDetail(snapshot.data[index]),
leading: Icon(
Icons.business_center,
color: Colors.blue,
),
trailing: IconButton(
icon: Icon(Icons.sort),
onPressed: () {
getDocIndex();
}),
);
},
separatorBuilder: (BuildContext context, int index) {
return Divider();
},
);
}
}),
);
}
}
class AdminsDetails extends StatefulWidget {
final DocumentSnapshot post;
AdminsDetails({this.post});
#override
_AdminsDetailsState createState() => _AdminsDetailsState();
}
String keyID;
class _AdminsDetailsState extends State<AdminsDetails> {
//Anfragen löschen intern
deleteDocument() async {
/* CollectionReference collectionReference =
Firestore.instance.collection("Requests");
QuerySnapshot querySnapshot = await collectionReference.getDocuments();
querySnapshot.documents[0].reference.delete();
*/
Firestore.instance.collection('Requests').document(keyID).delete();
}
//Anfragen intern ändern, anpassen! Button in der Appbar!
TextEditingController adminComment = TextEditingController();
updateData() async {
CollectionReference collectionReference =
Firestore.instance.collection("Requests");
QuerySnapshot querySnapshot = await collectionReference.getDocuments();
querySnapshot.documents[0].reference
.updateData({'Administrator Anmerkung': adminComment.text});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Anfrage von ${widget.post.data["Name"]}',
style: GoogleFonts.lexendDeca(),
),
centerTitle: true,
actions: [
IconButton(
icon: Icon(Icons.edit),
onPressed: () {
setState(() {
updateData();
});
})
],
),
body: SingleChildScrollView(
child: Container(
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Kontaktdaten des Kunden: ',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w200),
),
TextButton(
onPressed: () => customLaunch(
'mailto:${widget.post.data["Email"]}?subject=Feed%20back&body=Write your%20feedback'),
child: Text('Email: ${widget.post.data["Email"]}',
style: TextStyle(fontSize: 18)),
),
SizedBox(
child: Container(color: Colors.amber),
),
TextButton(
onPressed: () =>
customLaunch('tel: ${widget.post.data["Telefon"]}'),
child: Text('Telefon: ${widget.post.data["Telefon"]}',
style: TextStyle(fontSize: 18)),
),
Divider(),
Text(
'Kundenanschrift: ',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w200),
),
SizedBox(
height: 8.0,
),
TextButton(
child: Text('${widget.post.data["Anschrift"]}'),
onPressed: () => Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return MapsDemo();
})),
),
SizedBox(
height: 8.0,
),
Divider(),
Text(
'Kommentar:',
style: TextStyle(fontWeight: FontWeight.w200, fontSize: 18.0),
),
SizedBox(
height: 16.0,
),
Text('${widget.post.data["Kommentar"]}',
style: GoogleFonts.lexendDeca()),
Divider(),
Text(
'Details der Anfrage: ',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w200),
),
SizedBox(
height: 16.0,
),
Text('Anfrage vom: ${widget.post.data["Anfrage vom"]}',
style: GoogleFonts.lexendDeca()),
SizedBox(
height: 16.0,
),
Text('Küchenlänge: ${widget.post.data["Küchenlaenge"]} Meter',
style: GoogleFonts.lexendDeca()),
SizedBox(
height: 16.0,
),
Text('Hängeschränke: ${widget.post.data["Hängeschränke"]}',
style: GoogleFonts.lexendDeca()),
SizedBox(
height: 16.0,
),
Text(
'Gebrauchte Küche: ${widget.post.data["Gebrauchte Küche"]}',
style: GoogleFonts.lexendDeca()),
SizedBox(
height: 16.0,
),
Text(
'Arbeitsplatte schneiden: ${widget.post.data["Arbeitsplatte bearbeiten"]}',
style: GoogleFonts.lexendDeca()),
SizedBox(
height: 16.0,
),
Text(
'Anschluss Waschmaschine: ${widget.post.data["Anschluss WaMa"]}',
style: GoogleFonts.lexendDeca()),
SizedBox(
height: 16.0,
),
Text(
'Anschluss Spülmaschine: ${widget.post.data["Anschluss Spuel"]}',
style: GoogleFonts.lexendDeca()),
SizedBox(
height: 16.0,
),
Text(
'Anschluss Herd: ${widget.post.data["Anschluss Herd"]}',
style: GoogleFonts.lexendDeca(),
),
SizedBox(
height: 16.0,
),
Text(
'Wunschdatum Montage: ${widget.post.data["Wunschdatum"]}',
style: GoogleFonts.lexendDeca(),
),
SizedBox(
height: 16.0,
),
Text(
'Gesamt geschätzt: ${widget.post.data["Gesamt geschätzt"]} Euro',
style: GoogleFonts.lexendDeca(
fontSize: 18,
fontWeight: FontWeight.bold,
decoration: TextDecoration.underline),
),
TextField(
controller: adminComment,
decoration: InputDecoration(
hintText: 'Anmerkung Administrator:',
)),
//Kommentare von Administratoren:
Container(
child: Text(
'${widget.post.data['Administrator Anmerkung']}',
style: GoogleFonts.lexendDeca(),
)),
Column(
children: [
Center(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.red,
),
onPressed: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return AlertDialog(
title: Text('Diese Anfrage wirklich löschen?',
style: GoogleFonts.lexendDeca()),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Abbrechen')),
TextButton(
onPressed: () async {
setState(() {
deleteDocument();
Navigator.push(context,
MaterialPageRoute(builder:
(BuildContext context) {
return Admins();
}));
});
},
child: Text('Löschen')),
],
);
}));
},
child: Text('Anfrage löschen')),
),
],
),
],
),
),
),
),
);
}
}

My FlutterBarcodeScanner is outputing a `-1` when I press the cancel button in the scan screen

whenever I press the cancel button in the barcode/QR code scan screen, I get a -1 result on the output alert dialog. How do I Catch the number and replace it with a Text that makes sense to a user?
The Barcode/Qr Code Function
Future <void> scanqr() async {
final qrCode = await FlutterBarcodeScanner.scanBarcode(
"#ff6666", "Cancel", true, ScanMode.QR);
setState(() {
this.qrCode = qrCode;
});
showDialog(
context: context,
builder: (BuildContext context) => _buildPopupDialog(context));
}
The Alert Dialog Widget
Widget _buildPopupDialog(BuildContext context) {
return AlertDialog(
buttonPadding: EdgeInsets.all(15),
scrollable: true,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
title: Text(
"You Scanned the Following Product:",
style: TextStyle(),
),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
qrCode,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
),
],
),
actions: <Widget>[
GestureDetector(
onTap: scanqr,
child: Text(
"Re-Scan",
style: TextStyle(fontSize: 20, color: Colors.amber),
),
),
GestureDetector(
onTap: () => Navigator.of(context).push(
MaterialPageRoute(builder: (context) => Home_page()),
),
child: Text(
"Home",
style: TextStyle(fontSize: 20, color: Colors.amber),
),
)
]);
}
at 8 month ago of the question, I have a solution, inside of Future function I handled like this:
if (barcodeScanRes != "-1") {
setState(() {
_scanBarcode = barcodeScanRes;
});
} else {
setState(() {
_scanBarcode = "Scan canceled";
});
}

How to pass data from alertdialog to page in flutter?

I am passing data from my alertdialog to item of listview.
Where I can find information about it?
I tried use TextEditingController, with Navigation Routes. And I used materials from this Tutorial
This is my code:
class MeasurementsScreen extends StatefulWidget {
#override
_MeasurementsScreenState createState() => _MeasurementsScreenState();
}
class _MeasurementsScreenState extends State<MeasurementsScreen> {
List<_ListItem> listItems;
String lastSelectedValue;
var name = ["Рост", "Вес"];
var indication = ["Введите ваш рост", "Введите ваш вес"];
TextEditingController customcintroller;
void navigationPageProgrammTrainingHandler() {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => ProgrammTrainingHandler()),
);
}
#override
void initState() {
super.initState();
initListItems();
}
Future<String> createAlertDialog(BuildContext context, int indexAl){
customcintroller = TextEditingController();
if(indexAl < 2){
return showDialog(context: context, builder: (context){
return AlertDialog(
title: Text(name[indexAl]),
content: TextField(
textDirection: TextDirection.ltr,
controller: customcintroller,
style: TextStyle(
color: Colors.lightGreen[400],
fontSize: 18.5),
decoration: InputDecoration(
contentPadding: EdgeInsets.only(bottom: 4.0),
labelText: indication[indexAl],
alignLabelWithHint: false,
),
keyboardType: TextInputType.phone,
textInputAction: TextInputAction.done,
),
actions: <Widget>[
FlatButton(
child: const Text('ОТМЕНА'),
onPressed: () {
Navigator.of(context).pop();
},
),
FlatButton(
child: const Text('ОК'),
onPressed: () {
Navigator.of(context).pop(customcintroller.text.toString());
},
),
],
);
});
} else if (indexAl > 1){
navigationPageProgrammTrainingHandler();
}
}
#override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Color(0xff2b2b2b),
appBar: AppBar(
title: Text(
'Замеры',
style: new TextStyle(
color: Colors.white,
),),
leading: IconButton(
icon:Icon(Icons.arrow_back),
color: Colors.white ,
onPressed:() => Navigator.of(context).pop(),
),
),
body: ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: listItems.length,
itemBuilder: (BuildContext ctxt, int index){
return GestureDetector(
child: listItems[index],
onTap: () {
createAlertDialog(context, index).then((onValue){
});
}
);
},
),
);
}
void initListItems() {
listItems = [
new _ListItem(
bgName: 'assets/images/soso_growth.jpg',
name: customcintroller.text.toString().isEmpty == false ? customcintroller.text.toString() : "Рост",
detail: "Нажми, чтобы добавить свой рост"),
new _ListItem(
bgName: 'assets/images/soso_weight.jpg',
name: customcintroller.text.toString().isEmpty == false ? customcintroller.text.toString() : "Вес",
detail: "Нажми, чтобы добавить свой вес"),
new _ListItem(
bgName: 'assets/images/soso_chest.jpg',
name: "Грудь",
detail: "PRO-версия"),
new _ListItem(
bgName: 'assets/images/soso_shoulder.jpg',
name: "Плечи",
detail: "PRO-версия"),
new _ListItem(
bgName: 'assets/images/soso_biceps.jpg',
name: "Бицепс",
detail: "PRO-версия")
];
}
}
class _ListItem extends StatelessWidget {
_ListItem({this.bgName, this.name, this.detail});
// final int index;
final String bgName;
final String name;
final String detail;
#override
Widget build(BuildContext context) {
return Container(
height: 180.0,
margin: const EdgeInsets.symmetric(
vertical: 1.0,
),
child: new Stack(
children: <Widget>[
new Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage(bgName),
colorFilter: new ColorFilter.mode(
Colors.black.withOpacity(0.45), BlendMode.darken),
fit: BoxFit.cover,
alignment: Alignment.center),
),
child: new SizedBox.expand(
child: Container(
alignment: Alignment.center,
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Text(
name,
style: new TextStyle(fontSize: 29.0, color: Colors.white),
),
Padding(
padding: const EdgeInsets.only(top: 12.0),
child: new Text(
detail,
style:
new TextStyle(fontSize: 16.0, color: Colors.white),
),
)
],
),
),
),
),
],
),
);
}
}
I expect to get text from alertdialog.
Do you want to update data in your current screen or in another Scaffold/screen? Solution for the first option would be to set your desired data in a setState or pass it to a Model (with ScopedModel) and update the view. E.g. :
FlatButton(
child: const Text('ОТМЕНА'),
onPressed: () {
setState(() {
myData = data;
Navigator.of(context).pop();
}); // not sure if this will work, could you try?
}
),
If it is in a new/other screen, you can pass it in the Navigator like for example:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NewScreen(data: myData),
),
);
},
Does this solve your problem? Otherwise, please elaborate on what it is you need.
I tried to use Navigator.of(context).pop("OK"); in the AlertDialog but it doesn't work.
use ValueChanged as a param on the showDialog method and it works well.
class Dialogs{
static showAlertDialog(BuildContext context, String title, String message,
{List<String> actions, ValueChanged onChanged}) async {
if (actions == null) {
actions = ["OK"];//default OK button.
}
await showDialog(
context: context,
child: AlertDialog(
title: Text(title ?? 'Message'),
content: Text(message),
actions: actions
.map((e) => new FlatButton(
child: Text(e.trim()),
onPressed: () {
Navigator.of(context).pop(e.trim());
if (onChanged != null) {
onChanged(e.trim());
}
}))
.toList(),
),
);
}
}
the caller looks like
_onProcess(){
String result = "";
await Dialogs.showAlertDialog(context, "Warning", "Warning message", actions: ["OK", "Cancel"],
onChanged: (value) {
result = value;
});
if (result != "OK") {
Dialogs.showSnackBarMessage(context, "Cancel This PTN");
return;
}
....process with the OK logic.
}
If you want to change an item of the list you can do that with setState() before calling Navigator.pop(). It is not possible to pass data through Navigator.pop() though, as you may be able to do with Navigator.push(... MyPage(data)).
You could achieve what you want through State management. You can check for state management tutorials in general. But the two practices that are used most in my opinion are Scoped Model and BLoC pattern. These practices help you pass data through the widget tree back and forward. I would recommend BLoC pattern there are many tutorials about it. Also there is a package which can be very helpful with BLoC pattern: flutter_bloc.