flutter form save issue - forms

The below code works fine, I click the flat button and the alert dialog popup.
Questions:
1) But if I add the form.save, it shows error
flutter: The following NoSuchMethodError was thrown while handling a
gesture: flutter: The setter 'clientName=' was called on null.
flutter: Receiver: null flutter: Tried calling: clientName="423"
2) How to get the text input value such us: clientName..etc. I always get null. Pleas help.
class _formState extends State<form> {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
Booking booking;
#override
Widget build(BuildContext context) {
final getCourse = widget.course;
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
//title: Text('${widget.course.title}\n地址: ${widget.course.address}\nTEL: ${widget.course.tel}'),
title: Text('即日訂位'),
),
body: Container(
child: Form(
key: formKey,
child: ListView(
children: <Widget>[
ListTile(
leading: Icon(Icons.person_outline),
title: TextFormField(
initialValue: "",
onSaved: (val) => booking.clientName = val,
validator: (val) => val == "" ? val : null,
decoration: new InputDecoration(
labelText: "Name",
),
),
),
//Send or Post button
FlatButton(
textColor: Colors.blueAccent,
child: Text("OK"),
color: Colors.transparent,
onPressed: () {
_showFormDialog();
SystemChannels.textInput.invokeMethod('TextInput.hide');
},
)
],
),
),
),
);
}
void _showFormDialog() {
final FormState form = formKey.currentState;
if (form.validate()) {
//form.save();
var alert = new AlertDialog(
content: new Row(
children: <Widget>[
Text("hihi")
],
),
actions: <Widget>[
new FlatButton(
onPressed: () {
form.reset();
Navigator.pop(context);
},
child: Text("ok")),
new FlatButton(onPressed: () => Navigator.pop(context),
child: Text("cancel"))
],
);
showDialog(context: context,
builder: (_) {
return alert;
});
}
else {
var alert = new AlertDialog(
content:
new Row(
children: <Widget>[
Text("error!")
],
),
actions: <Widget>[
new FlatButton(onPressed: () => Navigator.pop(context),
child: Text("OK"))
],
);
showDialog(context: context,
builder: (_) {
return alert;
});
}
}
}

You have to initialize your Booking object first, try this:
Booking booking = new Booking();

Related

I was trying to show user a feedback message to in password reset by Email, But it's not working

I'm creating a reset password page for my flutter app and I'm using showDialog for giving the feedback to the user to, but while running the code the message does not appear in screen, kindly check the code and tell me is there any mistate which I have made.
If anyone know the solution please help, I was trying to solve it but I can't find any solution.
The code is below:
class ForgotPasswordMailScreen extends StatefulWidget {
const ForgotPasswordMailScreen({Key? key}) : super(key: key);
#override
State<ForgotPasswordMailScreen> createState() =>
_ForgotPasswordMailScreenState();
}
final TextEditingController _email = TextEditingController();
class _ForgotPasswordMailScreenState extends State<ForgotPasswordMailScreen> {
final formKey = GlobalKey<FormState>();
bool loading = false;
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.transparent,
leading: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: const Icon(
Icons.arrow_back_ios_new,
color: Colors.blue,
),
),
),
body: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.all(kDefaultSize),
child: Column(
children: [
const SizedBox(height: kDefaultSize * 4),
const FormHeaderWidget(
image: kForgotPasswordImage,
title: kForgotPassword,
subTitle: kForgotEmailTitle,
crossAxisAlignment: CrossAxisAlignment.center,
heightBetween: 10.0,
textAlign: TextAlign.center,
),
const SizedBox(height: kFormHeight),
Form(
key: formKey,
child: Column(
children: [
TextFormField(
controller: _email,
validator: (value) {
if (value!.isEmpty ||
!RegExp(r'^[\w-\.]+#([\w-]+\.)+[a-z]{2,5}$')
.hasMatch(value)) {
return 'Enter a valid email address.';
} else {
return null;
}
},
decoration: const InputDecoration(
label: Text(kEmail),
hintText: kEmail,
prefixIcon: Icon(Icons.mail_outline_rounded),
),
),
const SizedBox(height: 20.0),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () async {
if (formKey.currentState!.validate()) {
resetPassword();
formKey.currentState?.reset();
// _email.clear();
}
},
child: const Text(kNext),
),
),
],
),
),
],
),
),
),
),
);
}
// showLoadingScreen() {}
showMessage() {
showDialog(
context: context,
builder: (context) {
return const AlertDialog(
content: Text('Password reset link sent! Check your email.'),
);
});
}
showErrorMessage(String eMsg) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text(eMsg),
);
});
}
resetPassword() async {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => const Center(
child: CircularProgressIndicator(),
),
);
try {
await FirebaseAuth.instance
.sendPasswordResetEmail(email: _email.text.trim())
.then((value) {
Navigator.pop(context);
});
showMessage();
} on FirebaseAuthException catch (e) {
String error = e.message.toString();
showErrorMessage(error);
Navigator.pop(context);
}
}
}

RangeError (index) Flutter

I am getting an error and red screen while trying to click a button. RangeError (index): Invalid value: Valid value range is empty: 0. I do not know how to fix this error because nothing is flagged until I run my emulator. I have attached my
If I need to add some code please let me know I am more than willing to. Thank you!
home_page.dart
import 'package:flutter/material.dart';
import 'package:timestudy_test/pages/study_page.dart';
import 'package:timestudy_test/pages/timer_page.dart';
import 'package:timestudy_test/viewmodels/study_viewmodel.dart';
class HomePage extends StatefulWidget {
#override
State createState() => HomePageState();
}
class HomePageState extends State<HomePage> {
TextEditingController textController = new TextEditingController();
late String filter;
#override
void initState() {
textController.addListener(() {
setState(() {
filter = textController.text;
});
});
super.initState();
}
#override
void dispose() {
textController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text('TimeStudyApp'),
),
body: Material(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 8.0, left: 16.0, right: 16.0),
child: TextField(
style: TextStyle(fontSize: 18.0),
decoration: InputDecoration(
prefixIcon: Icon(Icons.search),
suffixIcon: IconButton(
icon: Icon(Icons.close),
onPressed: () {
textController.clear();
FocusScope.of(context).requestFocus(FocusNode());
},
),
hintText: "Search...",
),
controller: textController,
)),
Expanded(
child: StudyViewModel.studies.length > 0
? ListView.builder(
itemCount: StudyViewModel.studies.length,
itemBuilder: (BuildContext context, int index) {
if (filter == null || filter == "") {
return buildRow(context, index);
} else {
if (StudyViewModel.studies[index].name
.toLowerCase()
.contains(filter.toLowerCase())) {
return buildRow(context, index);
} else {
return Container();
}
}
},
)
: Center(
child: Text('No studies found!'),
),
)
],
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () async {
int? nullableInterger;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => StudyPage(
title: 'Add a study',
selected: nullableInterger ?? 0,
)));
},
),
);
}
Widget buildRow(BuildContext context, int index) {
return ExpansionTile(
title: Text(StudyViewModel.studies[index].name, style: TextStyle(fontSize: 18.0)),
children: <Widget>[
ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemCount: StudyViewModel.studies[index].tasks.length,
itemBuilder: (context, int taskIndex) {
return ListTile(
title: Text(StudyViewModel.studies[index].tasks[taskIndex].name),
contentPadding: EdgeInsets.symmetric(horizontal: 32.0),
subtitle: Text(
StudyViewModel.studies[index].tasks[taskIndex].elapsedTime),
trailing: IconButton(
icon: Icon(
Icons.timer
),
onPressed: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => TimerPage(
task: StudyViewModel
.studies[index].tasks[taskIndex])));
},
),
);
},
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
IconButton(
icon: Icon(
Icons.edit
),
onPressed: () async {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => StudyPage(
title: StudyViewModel.studies[index].name,
selected: index)));
},
),
IconButton(
icon: Icon(
Icons.delete
),
onPressed: () async {
await showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text('Do you wish to delete this study?'),
actions: <Widget>[
FlatButton(
child: Text('Accept'),
onPressed: () async {
StudyViewModel.studies.removeAt(index);
await StudyViewModel.saveFile();
Navigator.of(context).pop();
},
),
FlatButton(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
});
},
),
],
),
],
);
}
}
study_page.dart
import 'package:flutter/material.dart';
import 'package:timestudy_test/models/study.dart';
import 'package:timestudy_test/models/task.dart';
import 'package:timestudy_test/viewmodels/study_viewmodel.dart';
class StudyPage extends StatefulWidget {
final String title;
final int selected;
StudyPage({required this.title, required this.selected});
#override
State createState() => StudyPageState();
}
class StudyPageState extends State<StudyPage> {
late Study study;
late TextField nameField;
TextEditingController nameController = new TextEditingController();
late TextField taskNameField;
TextEditingController taskNameController = new TextEditingController();
#override
void initState() {
nameField = new TextField(
controller: nameController,
decoration: InputDecoration(
labelText: 'Study name'),
);
taskNameField = new TextField(
controller: taskNameController,
decoration:
InputDecoration(labelText: 'Task name'),
);
if(widget.selected != null) {
study = StudyViewModel.studies[widget.selected];
nameController.text = study.name;
} else {
study = new Study(
name: "",
tasks: <Task>[]
);
}
super.initState();
}
#override
void dispose() {
nameController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text(widget.title),
),
body: Material(
child: Padding(padding: EdgeInsets.all(16.0), child: Column(
children: <Widget>[
Padding(padding: EdgeInsets.only(bottom: 8.0), child: nameField),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Tasks:', style: TextStyle(fontSize: 18.0),),
IconButton(
icon: Icon(Icons.add),
onPressed: () async {
await showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Add a task'),
content: taskNameField,
actions: <Widget>[
FlatButton(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
FlatButton(
child: Text('Accept'),
onPressed: () {
if(taskNameController.text == ""){
errorDialog(context, 'Please enter a task name!');
} else {
setState(() {
study.tasks.add(new Task(
name: taskNameController.text,
elapsedTime:
StudyViewModel.milliToElapsedString(
0)));
taskNameController.clear();
});
Navigator.of(context).pop();
}
},
),
],
);
});
},
)
],
),
Expanded(
child: ListView.builder(
itemCount: study.tasks.length,
itemBuilder: (context, int index) {
return ListTile(
title: Text(study.tasks[index].name),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
setState(() {
study.tasks.removeAt(index);
});
},
),
);
},
),
), Spacer(),
Center(
child: RaisedButton(
color: Theme.of(context).accentColor,
child: Text('Save'),
onPressed: () async {
if (nameController.text == "") {
errorDialog(context, 'Please enter a study name!');
} else {
if (study.tasks.length < 1) {
errorDialog(context, 'Please add at least one task!');
} else {
study.name = nameController.text;
if (widget.selected != null) {
StudyViewModel.studies[widget.selected] = study;
await StudyViewModel.saveFile();
Navigator.of(context).pop();
} else {
if (StudyViewModel.checkName(nameController.text)) {
errorDialog(context, 'Study name already taken!');
} else {
StudyViewModel.studies.add(study);
await StudyViewModel.saveFile();
Navigator.of(context).pop();
}
}
}
}
},
))
],
),
)));
}
void errorDialog(BuildContext context, String message) async {
await showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text(message),
actions: <Widget>[
FlatButton(
child: Text('Close'),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
}
);
}
}
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () async {
int? nullableInterger;
// the issue is here you need to assign value
// the nullableInterger is use here as nothing.. declare it on state level and
// assign it when your listview builder done so the value of nullable integer is
// changed and passing value as argument will not be 0 and this error will not appear again
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => StudyPage(
title: 'Add a study',
selected: nullableInterger ?? 0,
)));
},
),

Class <QuerySnapshot> has no instance getter 'documents'.Reciever : Instance of 'QuerySnapshot'

I have a to do app which lists all todos in in a screen
This is my listview
class assignedTask extends StatefulWidget {
static const String id = 'assignedTask';
#override
_assignedTaskState createState() => _assignedTaskState();
}
class _assignedTaskState extends State<assignedTask> {
String Title;
String Summary;
var tasks;
crudMedthods crudObj = new crudMedthods();
var documentID;
var documents;
Future<bool> addDialog(BuildContext context) async {
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Add Data', style: TextStyle(fontSize: 15.0)),
content: Container(
height: 125.0,
width: 150.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
decoration: InputDecoration(hintText: 'Enter Title'),
onChanged: (value) {
this.Title = value;
},
),
SizedBox(height: 5.0),
TextField(
decoration: InputDecoration(hintText: 'Enter Summary'),
onChanged: (value) {
this.Summary = value;
},
),
],
),
),
actions: <Widget>[
FlatButton(
child: Text('Add'),
textColor: Colors.blue,
onPressed: () {
Navigator.of(context).pop();
crudObj.addData({
'Title': this.Title,
'Summary': this.Summary
}).then((result) {
dialogTrigger(context);
}).catchError((e) {
print(e);
});
},
)
],
);
});
}
Future<bool> updateDialog(BuildContext context, selectedDoc) async {
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Update Data', style: TextStyle(fontSize: 15.0)),
content: Container(
height: 125.0,
width: 150.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
decoration: InputDecoration(hintText: 'Title'),
onChanged: (value) {
this.Title = value;
},
),
SizedBox(height: 5.0),
TextField(
decoration: InputDecoration(hintText: 'Enter Summary'),
onChanged: (value) {
this.Summary = value;
},
),
],
),
),
actions: <Widget>[
FlatButton(
child: Text('Update'),
textColor: Colors.blue,
onPressed: () {
Navigator.of(context).pop();
crudObj.updateData(selectedDoc, {
'Title': this.Title,
'Summary': this.Summary
}).then((result) {
// dialogTrigger(context);
}).catchError((e) {
print(e);
});
},
)
],
);
});
}
Future<bool> dialogTrigger(BuildContext context) async {
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Job Done', style: TextStyle(fontSize: 15.0)),
content: Text('Added'),
actions: <Widget>[
FlatButton(
child: Text('Alright'),
textColor: Colors.blue,
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
}
#override
void initState() {
crudObj.getData().then((results) {
setState(() {
tasks = results;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Assigned Tasks'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
onPressed: () {
addDialog(context);
},
),
IconButton(
icon: Icon(Icons.refresh),
onPressed: () {
crudObj.getData().then((results) {
setState(() {
tasks = results;
});
});
},
)
],
),
body: _TaskList(),
);
}
Widget _TaskList() {
if (tasks != null) {
return StreamBuilder(
stream: tasks,
// ignore: missing_return
builder: (context, snapshot) {
if (snapshot.data != null) {
return ListView.builder(
itemCount: snapshot.data.documents.length,
padding: EdgeInsets.all(7.0),
itemBuilder: (context, i) {
return ListTile(
title: Text(snapshot.data.documents[i].data["Title"]??""),
subtitle: Text(snapshot.data.documents[i].data["Summary"]??""),
/*onTap: () {
*//*
updateDialog(
context, snapshot.data.documents[i].documentID);
},*/
onTap: (){
Navigator.push(context,MaterialPageRoute(builder:(context)=>DetailPage(snapshot.data.douments[i])));
}, onLongPress: () {
crudObj.deleteData(snapshot.data.documents[i].documentID);
},
);
},
);
}
return CircularProgressIndicator();
},
);
} else {
return Text('Loading, Please wait..');
}
}
}
When i press ontap it should go to the detail page which shows details of only that particular task(note: i now have only the values Title and summary for now, i will add rest later they should show in the detail page)
My detailview is as follows
class DetailPage extends StatelessWidget {
DocumentSnapshot detailDocument;
DetailPage(this.detailDocument);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text( detailDocument.data["Title"]),
),
body: Center(
child: Text(detailDocument.data["Summary"]),
),
);
}
}
I am getting an error
The following NoSuchMethodError was thrown building Builder(dirty):
Class 'QuerySnapshot' has no instance getter 'douments'.
Receiver: Instance of 'QuerySnapshot'
Tried calling: douments
The relevant error-causing widget was:
MaterialApp file:///C:/Users/TRICON/AndroidStudioProjects/taskmanager/lib/main.dart:21:14
When the exception was thrown, this was the stack:
0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
1 _assignedTaskState._TaskList.... (package:taskmanager/screens/assignedtask.dart:208:106)
You are using
Navigator.push(context,MaterialPageRoute(builder:(context)=>DetailPage(snapshot.data.douments[i])));
instead of
Navigator.push(context,MaterialPageRoute(builder:(context)=>DetailPage(snapshot.data.documents[i])));
It's just a difference in the spelling of douments as documents.

flutter alert dialog for updating value

I want to update value in alert dialog i am using following:
Future showAlert() async {
await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Alert in Dialog'),
content: Container(
height: 40.0,
width: 60.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_itemCount != 1
? new IconButton(
icon: new Icon(Icons.remove),
onPressed: () => setState(() => _itemCount--),
)
: new Container(),
new Text(_itemCount.toString()),
new IconButton(
icon: new Icon(Icons.add),
onPressed: () => setState(() => _itemCount++))
],
),
),
actions: <Widget>[
new FlatButton(
child: new Text('CANCEL'),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
}
I am calling this function in Listview Builder
GestureDetector(
child: Align(
alignment: Alignment.topRight,
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Icon(Icons.add_box,
color: Color(0xFFfccd01)),
),
),
onTap: () {
showAlert();
/* FutureBuilder<String>(
future: Add_to_cart(USER_ID,
snapshot.data[index].id, "1"),
builder: (context, snapshot) {
print(snapshot.data);
});*/
},
),
But on + click my value of alert dialog is not going to update after i close and reopen it it will update but i want to update on tap of icon button.
You can use StreamBuilder to update within Dialog or that screen also on single event thru Streams
You must insert AlertDialog into Statefulll Widget
see this example:
class ShowDialog extends StatefulWidget {
#override
_ShowDialogState createState() => _ShowDialogState();
}
class _ShowDialogState extends State<ShowDialog> {
#override
Widget build(BuildContext context) {
return AlertDialog(
//your container
);
}
}
and call ShowDialog into showDialog()

Snackbar in SimpleDialog Flutter

I faced an error code below when adding a snackbar to an on-pressed method in my Simpledialog.
[Scaffold.of() called with a context that does not contain a Scaffold.]
I would like to seek your advice on how to provide the correct context to resolve it.
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new AlertApp()));
}
class AlertApp extends StatefulWidget {
#override
_AlertAppState createState() => _AlertAppState();
}
class _AlertAppState extends State<AlertApp> {
SimpleDialog _simdalog;
void sDialog(){
_simdalog = new SimpleDialog(
title: new Text("Add To Shopping Cart"),
children: <Widget>[
new SimpleDialogOption(
child: new Text("Yes"),
onPressed: (){
final snackBar = SnackBar(content: Text('Purchase Successful'));
Scaffold.of(context).showSnackBar(snackBar);
},
),
new SimpleDialogOption(
child: new Text("Close"),
onPressed:() {Navigator.pop(context);},
),
],
);
showDialog(context: context, builder: (BuildContext context){
return _simdalog;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: new Center(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new RaisedButton(
child: new Text("Add to Shopping Cart [Simple]"),
onPressed:(){
sDialog();
}),
],
),
),
);
}
}
Solution 1: as Mazin Ibrahim mentioned in comments Scaffold.of() called with a context that does not contain a Scaffold
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
...
Scaffold(
key: _scaffoldKey,
...
onPressed: () {
_scaffoldKey.currentState.showSnackBar(
SnackBar(
content: Text('Purchase Successful'),
duration: Duration(seconds: 3),
));
}
Solution 2:
With package flushbar, you can also display notification on top
Flushbar link : https://github.com/AndreHaueisen/flushbar
Another suggestion to use flushbar How to show snackbar after navigator.pop(context) in Flutter?
Flushbar(
title: "Hey Ninja",
message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
flushbarPosition: FlushbarPosition.TOP,
flushbarStyle: FlushbarStyle.FLOATING,
reverseAnimationCurve: Curves.decelerate,
forwardAnimationCurve: Curves.elasticOut,
backgroundColor: Colors.red,
boxShadows: [BoxShadow(color: Colors.blue[800], offset: Offset(0.0, 2.0), blurRadius: 3.0)],
backgroundGradient: LinearGradient(colors: [Colors.blueGrey, Colors.black]),
isDismissible: false,
duration: Duration(seconds: 4),
icon: Icon(
Icons.check,
color: Colors.greenAccent,
),
mainButton: FlatButton(
onPressed: () {},
child: Text(
"CLAP",
style: TextStyle(color: Colors.amber),
),
),
showProgressIndicator: true,
progressIndicatorBackgroundColor: Colors.blueGrey,
titleText: Text(
"Hello Hero",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 20.0, color: Colors.yellow[600], fontFamily: "ShadowsIntoLightTwo"),
),
messageText: Text(
"You killed that giant monster in the city. Congratulations!",
style: TextStyle(fontSize: 18.0, color: Colors.green, fontFamily: "ShadowsIntoLightTwo"),
),
)..show(context);
You can return a bool from the showDialog method and use that to determine whether to show the snackbar:
void main() {
runApp(MaterialApp(
home: AlertApp(),
));
}
class AlertApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
MyShoppingButton(),
],
),
),
);
}
}
// Separate out the button from _AlertAppState so that the call to
// showSnackBar comes from a different BuildContext
class MyShoppingButton extends StatelessWidget {
#override
Widget build(BuildContext context) {
return RaisedButton(
child: Text("Add to Shopping Cart [Simple]"),
// Use an async onPressed method so that we can wait for the
// result from the dialog before deciding whether to show the snackbar
onPressed: () async {
bool result = await showDialog<bool>(
context: context,
builder: (BuildContext context) {
return MyShoppingDialog();
},
);
// Check if result is null below as Flutter will throw Exception if
// tries determining whether to enter an if branch will a null boolean
if (result != null && result) {
final snackBar = SnackBar(content: Text('Purchase Successful'));
Scaffold.of(context).showSnackBar(snackBar);
}
},
);
}
}
class MyShoppingDialog extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SimpleDialog(
title: Text("Add To Shopping Cart"),
children: <Widget>[
SimpleDialogOption(
child: Text("Yes"),
onPressed: () {
// Pop with a result of true so that MyShoppingButton
// knows to show snackbar. In any other case
// (including the user dismissing the dialog), MyShoppingButton
// null receive null, and so will not show the snackbar
Navigator.of(context).pop(true);
},
),
SimpleDialogOption(
child: Text("Close"),
onPressed: () {
Navigator.pop(context);
},
),
],
);
}
}
You should create a Scaffold widget inside of showDialog and a Builder widget as child of the Scaffold and pass context as parameter.
void sDialog({BuildContext context}){
_simdalog = new SimpleDialog(
title: new Text("Add To Shopping Cart"),
children: <Widget>[
new SimpleDialogOption(
child: new Text("Yes"),
onPressed: (){
final snackBar = SnackBar(content: Text('Purchase Successful'));
Scaffold.of(context).showSnackBar(snackBar);
},
),
new SimpleDialogOption(
child: new Text("Close"),
onPressed:() {Navigator.pop(context);},
),
],
);
showDialog(context: context, builder: (BuildContext context){
return GestureDetector(
onTap: (){Navigator.of(context).pop();},
child: Scaffold(
body: Builder(
builder: (context){
return _simdalog(context: context);
}
),
),);
});
}