How can I leave a function? Dart/Flutter - flutter

Hey I have an ElevatedButton with an onPressed. Inside the onPressed are some if-statements that ensure that everything is correct and afterwards I want to push these information to firebase. How can I leave the onPressed function if a condition is not fulfilled? I tried return and return null, return 0 but my App is just freezing.
ElevatedButton(
onPressed: () async {
if (date != null) {
print(date);
} else {
dialog.showAlertDialog(context, 'Oops', 'You didn\'t choose a date!');
return;
}
if (time != null) {
print(time);
} else {
dialog.showAlertDialog(context, 'Oops', 'You didn\'t choose a time!');
return 0;
}
if(combinedDateAndTime.isBefore(DateTime.now())) {
dialog.showAlertDialog(context, 'Oops', 'Your date and time is in the past');
return null;
}
_firestore.collection('foo').add({
'dateTime': combinedDateAndTime,
});
},
style: raisedButtonStyle,
),
),
I just couldn't figure out how to leave the function. I would appreciate any help.

one way is that define a boolean variable and check if it is true then firestore.collection called, somthing like this :
bool var = true;
if (date != null) {
print(date);
} else {
dialog.showAlertDialog(context, 'Oops', 'You didn\'t choose a date!');
var = false;
}
if (time != null) {
print(time);
} else {
dialog.showAlertDialog(context, 'Oops', 'You didn\'t choose a time!');
var = false;
}
if(combinedDateAndTime.isBefore(DateTime.now())) {
dialog.showAlertDialog(context, 'Oops', 'Your date and time is in the past');
var = false;
}
if (var == true){
_firestore.collection('foo').add({
'dateTime': combinedDateAndTime,
});
}

Related

How to use function output as a conditional of IF ELSE or Ternary operator

So for some background, I implemented a function that reads from Firebase's real-time database and returns a child node. I have built a button that is meant to check if that function returns the object or null if the function returns an object I want the snack bar to display a message.
ElevatedButton(
onPressed: () {
if (validateUsername() != null) {
print("conditional: test");
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text(
"Username has been taken please try a different one"),
duration: Duration(seconds: 5)));
} else {
return null;
}
},
I had some success with the function by turning it into an async function
validateUsername() async {
final database = FirebaseDatabase.instance.ref().child("/takenUsernames");
await database
.child(_usernameController.text.trim())
.once()
.then((DatabaseEvent event) {
final snapShot = event.snapshot;
final value = snapShot.value;
print("function result: $value");
return value;
});
}
When I turn it to an async function the snack bar displays the message but unfortunately even when the conditional is equal to a null, it for some reason continues to display the message and prints the "test"output. But if I were to try taking away the async the snack bar doesn't print and the "test" in the conditional doesn't print.non-async output
Any help would be appreciated and thanks for your time.
Try this approach, using the await in a variable will wait for the value then the if will evaluate what the result.
ElevatedButton(
onPressed: () async {
String validation = await validateUsername(); // I used type String but you should use the type that will be return.
if (validation != null) {
print("conditional: test");
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text(
"Username has been taken please try a different one"),
duration: Duration(seconds: 5)));
} else {
return;
}
},
)
add try/catch
validateUsername() async {
try {
final database = FirebaseDatabase.instance.ref().child("/takenUsernames");
await database
.child(_usernameController.text.trim())
.once()
.then((DatabaseEvent event) {
final snapShot = event.snapshot;
final value = snapShot.value;
print("function result: $value");
return value;
});
} catch(e) {
print("err $e");
return null;
}
}
Thanks to some help from #WilsonToribio, I was able to use the information he gave and also implement a few changes to the validateUsername() function
as seen here
validateUsername() async {
try {
final database = FirebaseDatabase.instance.ref().child("/usernames");
final response = await database
.child(_usernameController.text.trim())
.once()
.then((event) {
final dataSnapshot = event.snapshot;
if (dataSnapshot.value != null) {
return dataSnapshot.value;
}
});
return response;
} catch (e) {
print("err $e");
return null;
}
}

How to call button tap functionality outside of button in Flutter

I want to call the onTap functionality outside of my button. As soon as I receive my OTP, I want to call the onTap of my manually created widget. I have a custom widget called as LoginCTA and I want to call it's onTap after I receive my OTP in initSmsListener method which I called in initState.
My code -
String _comingSms = 'Unknown';
Future<void> initSmsListener() async {
String comingSms;
try {
comingSms = await AltSmsAutofill().listenForSms??"";
} on PlatformException {
comingSms = 'Failed to get Sms.';
}
if(!mounted)
return;
setState(() {
_comingSms=comingSms;
print("\n \n \n Coming SMS - $_comingSms");
otpController.text = _comingSms[23] + _comingSms[24] + _comingSms[25] + _comingSms[26]
+ _comingSms[27] + _comingSms[28];
});
//Apply here -
}
#override
void initState() {
initSmsListener();
super.initState();
}
isOTP
? LoginCTA(
//After input otp
onPressed: () async {
print(Provider.of<APIData>(context, listen: false)
.loggedIN);
if (emailEntered &&
otpController.text.length == 6) {
bool res;
try {
res = await widget.signInWithOTP(
contactController.text, otpController.text);
} catch (e) {
res = false;
print(e);
}
if (res) {
Fluttertoast.showToast(
msg: "Verifying OTP...",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
textColor: cardColor,
backgroundColor: primaryTextColor,
fontSize: 16.0,
);
Timer(Duration(seconds: 2), () {
print(Provider.of<APIData>(context,
listen: false)
.loggedIN);
if (Provider.of<APIData>(context,
listen: false)
.loggedIN ==
1) {
Navigator.pop(context);
}
});
}
}
},
btnText: otpButtonText,
isDisabled: isDisabled,
)
: LoginCTA(
//After input mobile number
onPressed: () async {
if (emailEntered &&
contactController.text.length == 10) {
widget.sendOTP(contactController.text);
setState(() {
isOTP = true;
isDisabled = true;
});
} else {
print('kuch na kuch glti');
}
},
btnText: buttonText,
isDisabled: isDisabled,
hasIcon: hasIcon,
),
Just extract the functionality out into its own function. Then you can assign the function to onTap and also call it whenever you like.

DropdownButtonFormField call with class can't assign chosen value after method call

I am trying to work on a project and I am fairly new to Flutter.
I have this DropdownButtonFormField<ClassNoSearch> and value is _currentClassNoSearch that is an object ClassNoSearch _currentClassNoSearch;
After I choose an item from this list, _getData(); function is called and it sets the _currentClassNoSearch; to null.
I don't want this to happen, instead, I want the chosen value to be the same after _getData(); but I can't seem to delete the _currentClassNoSearch = null; line.
DropdownButtonFormField<ClassNoSearch> :
DropdownButtonFormField<ClassNoSearch>(
hint: Text("Hint"),
isExpanded: true,
value: _currentClassNoSearch,
style: TextStyle(
color: Colors.black,
fontSize: 16.0,
),
icon: Icon(
Icons.arrow_drop_down,
),
onChanged: (ClassNoSearch newVal) {
setState(() {
_currentClassNoSearch = newVal;
});
_getData();
},
_getData();
Future<HomeworkSudo> _getData() {
if (_currentClassNoSearch == null) {
return getHomeworkSudo("").then((HomeworkSudo result) {
setState(() {
activeHomeworkList = result.activeHomeWork;
inactiveHomeworkList = result.passivHomeWork;
classNoList = result.classNo;
});
return result;
});
} else {
return getHomeworkSudo(_currentClassNoSearch.userClassDepartmentId)
.then((HomeworkSudo result) {
setState(() {
_currentClassNoSearch = null;
activeHomeworkList = result.activeHomeWork;
inactiveHomeworkList = result.passivHomeWork;
classNoList = result.classNo;
});
return result;
});
}
}
As you can see If I delete the line that sets _currentClassNoSearch = null; i get the error below . Any ideas on how I should approach this?
items == null || items.isEmpty || value == null
Either zero or 2 or more DropdownMenuItems were detected with the same value.
The code says the following assertion failed:
items == null || items.isEmpty || value == null
You don't include items in your code, so items is set to null by default, which is why the assertion fails.

flutter : disable button after fetch data

I am trying to implement a flutter app to fetch data from an API end point. I've already implemented the fetch function on button press.
Although, I want the button (Enregistrer) to get disabled (to avoid multiple clicks) while the request is being fetched or after success editing (name, adress ...) !
I implemented it using the dart http package.
Here's my code for the same:
Container(
margin: EdgeInsets.symmetric(
vertical: 10),
width: size.width * 0.4,
child: ElevatedButton(
onPressed: () {
if (_nameController.text ==
"" &&
_emailController.text ==
"" &&
_adressController
.text ==
"") {
setState(() =>
isButtonDisabled =
true);
} else {
editUserProfile();
}
},
child: Text('Enregistrer'),
void editUserProfile() async {
setState(() {});
// if (_formKey.currentState.validate()) {
String name = _nameController.text;
String email = _emailController.text;
String adress = _adressController.text;
userApi.editUserProfile(name, email, adress).then((data) {
if (data != null) {
}
setState(() {
enableup = false;
enableadress = false;
enableemail = false;
});
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(data)));
// ScaffoldMessenger.of(context).showSnackBar(snackBar3);
}).catchError((error) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(error.toString())));
});
setState(() {});
}
if you set null onPressed you actualy disable the click
onPressed: isButtonDisabled ? null : () {
if (_nameController.text == "" &&
_emailController.text == "" &&
_adressController.text == "") {
setState(() =>
isButtonDisabled = true);
} else {
editUserProfile();
}
}

How to put an if statement in another one in flutter?

I am trying to put an if statement inside another like this :
void initState() {
super.initState();
FirebaseAuth.instance.currentUser().then((res) {
if (res != null) {
if (userType.text == 'Student') {
Navigator.pushReplacementNamed(context, '/StudentsPage');
} else if (userType.text == 'Teacher') {
Navigator.pushReplacementNamed(context, '/TeacherPage');
} else if (userType.text == 'Admin') {
Navigator.pushReplacementNamed(context, '/AdminPage');
}
} else {
LoginScreen();
}
});
}
But It gives me this error that there is a text that was called on null, so if anyone has an idea.
I'm using FireBase database.. and I am retrieving the data using this:
void getUserData() async {
try {
firestoreInstance .collection('Users') .document(usernameController.text) .get() .then((value) {
setState(() {
email = (value.data)['email'];
password = (value.data)['password'];
gender = (value.data)['gender'];
username = (value.data)['username'];
userType = (value.data)['userType'];
}); });
print('$userType');
}
catch (e) {
print(e.toString);
} }
The issue is that userType is a String object and therefore has no text getter method. Remove the .text and it seems that your code would work fine.
if (res != null) {
if (userType == 'Student') {
Navigator.pushReplacementNamed(context, '/StudentsPage');
} else if (userType == 'Teacher') {
Navigator.pushReplacementNamed(context, '/TeacherPage');
} else if (userType == 'Admin') {
Navigator.pushReplacementNamed(context, '/AdminPage');
}
}