How to handle null value in TextField. [Flutter] - flutter

In this app there are two screens, the first screen displays all the user input Strings in a List, and the second screen has a TextField which takes the user input which will return to the first screen using onEditingComplete. The user will be able to navigate to the second screen by using a FAB in the first screen. When the user does not type anything in the TextField and returns to the previous page, the String which stores the user input value returns "null". I have added an if statement which will only return to the first page if the TextField is not empty but when i click on submit, it does not navigate to the first screen at all.
Could i get a suggestion on how i can modify the code so that null value from the TextField will not save to the String and navigate back to the first screen.
FAB which navigates to input(second) screen:
FloatingActionButton(
onPressed: ()async {
// setstring(String result){
// widget.updatestring = result;
// return widget.updatestring;
// }
String result1 = await Navigator.push( // string which stores the user entered value
context,
MaterialPageRoute(
builder: (context) => InputScreen(), //screen which has TextField
));
setState(() {
// widget.updatestring = result1;
TodoList(result1);
// setstring(result1);
addItem(result1, false); // function which adds the entered task in a list
});
},
heroTag: "btn2",
child: Icon(Icons.add, color: Color(whitecolor),), backgroundColor: Color(redcolor),),
Textfield which takes user input :
TextField(
autofocus: true,
onEditingComplete: (){
String textToSendBack = taskcontroller.text;
if(taskcontroller.text.isNotEmpty) {
Navigator.pop(context, textToSendBack);
}
},
// onSubmitted: (value) {
// String textToSendBack = taskcontroller.text;
// Navigator.pop(context, value);
// },
maxLength: 100,
controller: taskcontroller,
decoration: InputDecoration(
labelText: "enter tasks here"
),
style: TextStyle(height: 1.2, fontSize: 20, color: Colors.black87),
)

For me it's working fine isEmpty or isNotEmpty
_titleController.text.isEmpty
_titleController.text.isNotEmpty

you can do something like this:
String textToSendBack = taskcontroller.text;
if(textToSendBack != null){
Navigator.pop(context, textToSendBack);
}
that will only take you back to the other screen when the Text isn't empty. otherwise, you stay on the current screen waiting for valid input.
I hope I understood you question correctly.

Related

How to make a button to have some active or inactive effect when a menu is being displayed and hidden in flutter (using "showMenu" )

I am using showMenu() function to create and render a menu when onTap() on a certain ListTile widget. So, How to make the ListTile show in an active/inactive state (using some background colour) when the menu is active and vice versa.
PS. I am able to achieve active state when the list tile is clicked using onTap() but unable to achieve the inactive state as I am unable to find a way of reverting the `List Tile background colour because there is no toggle/function when the pop-up menu from show menu is closed.
Please check the below images to get more clarity on the issue.
inactive state
active and menu open
menu closed but colour is still in effect
// List to maintain active states (item will be pushed to list on onTap() function)
List sideOptions = [];
// function to return color w.r.t if statements
Color changeBackground(bool isHovered, String sideOption) {
print(currentRoute);
if ((isHovered || (currentRoute == "/$sideOption")) ||
sideOptions.contains(sideOption)) {
return global_styles.blueShade;
} else {
return Colors.transparent;
}
}
// ListTile wrapped in a container
// OnHoverIcon() is a function i wrote to capture hover events if any
// ListTile onTap() function
_buildPopUpMenuButton(
String title, String iconString, List<PopupMenuEntry> subItems) {
child: OnHoverIcon(builder: (isHovered) {
return Container(
height: 55,
decoration: BoxDecoration(
color: changeBackground(isHovered, title),
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(8.0),
topRight: Radius.circular(8.0),
),
),
child: ListTile(
onTap: () => {
sideOptions.add(title),
if (!_isDropdownOpen)
{_controller.forward(), _isDropdownOpen = true}
else
{
_controller.reverse(),
_isDropdownOpen = false,
},
// _isDropdownOpen = true,
showMenu(
context: context,
position: getSizeandPosition(),
items: subItems)
},
leading: Image.asset(
iconString,
color: changeIconColors(isHovered, title),
),
title: Text(
title,
style: sideNavItems(isHovered, title),
),
trailing: title != "Settings"
? RotationTransition(
turns: _rotationAnimation,
child: Icon(
Icons.keyboard_arrow_up,
color: changeIconColors(isHovered, title),
),
)
: null,
),
);
}
);
}
}`
showMenu() returns a Future that ends when the menu is popped. So, you can place an await before it and it'll continue to the next line when the menu is popped.
Like this:
void onTap() async {
// Set the tile as active (changes the color to blue)
setState(() {
isActive = true;
});
// Show menu and wait for it to pop.
await showMenu(
/* ... */
);
// Menu is popped. Set the tile as inactive and return to the default color.
setState(() {
isActive = false;
});
}
Edit: It's best to extract the button to its own StatefulWidget so setState() will update just the button instead of the whole page.
If this doesn't work with your code. Maybe place a stateful widget in the menu and use dispose() to detect when it's no longer active and trigger the inactivation method.

Flutter Circular Progress Indicator On Submit Button

I have a Login screen and it has two text fields and a submit button, in this submit button, what im doing right now is that when its pressed it shows a loading icon and at some point it will navigate to the other screen, but if the usernames email and phone number is wrong i show a snackbar with and error message, the problem is that even when that happends the loading icon keeps loading and it never stops, what im want to do is that if everything is fine and the user can navigate to the other screen than show the loading icon and then the it will navigate to the other screen, and if the email or password are wrong in this case if response.statusCode is not equal to 200 i show the snackbar with the error message and i want loading icon to be false. same with if the text fields are empty, for now ive made a validator on my TextFormFields, so when the text fields are empty or response.statusCode != 200 loading = false
bool loading = true;
TextFormField loginEmailTextField() {
return TextFormField(
enableInteractiveSelection: false,
keyboardType: TextInputType.number,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your phone number';
}
return null;
},
TextFormField loginPasswordTextField() {
return TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your password';
}
return null;
},
ElevatedButton(
onPressed: () async {
if (_formKey.currentState!.validate()) {
Future<Response> futureResponse = fetchWorkingLocationData();
futureResponse
.then((response) => {
if (response.statusCode == 200)
{
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MenuPage()),
)
}
else
{
{
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
backgroundColor: Colors.blue,
content: Text(
"Incorrect phone number or password",
style: TextStyle(fontSize: 18),
),
duration: Duration(seconds: 4),
),
),
}
},
})
.catchError((error, stackTrace) => print('shush'));
}
if (loading) return;
setState(() {
loading = true;
});
},
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10),
child: loading
? Loading()
: Text(
'Submit',
I'm not sure if your isLoading is already outside (it seems so),but isLoading boolean should be outside of your main widget build function, because whenever you call setState your boolean will be set to true again, also I would set it to false instead because you don't want it showing immediately on the login page
In your button function you should also call setState and set your isLoading value to whatever it should be when that if check is done
.then((response) => {
if (response.statusCode == 200)
{
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MenuPage()),
)
}
else
{
{
setState(){
isLoading = false;
}
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
backgroundColor: Colors.blue,
content: Text(
"Incorrect phone number or password",
style: TextStyle(fontSize: 18),
),
duration: Duration(seconds: 4),
),
),
}
},
})
Basically what you want to do is set the state of that boolean whenever it should be set to either true or false
This has to be done for every case that you have in your button (both for the icon and the loading indicator)

How to show AllertDialog if Textfield is empty in Flutter

I'm building an application on flutter and i have a problem because of the list.
In flutter, I made an empty list, in this list filling by users. An assignment takes place when the user enters a value, but this always happens when a value is entered. If no value is entered, it reflects the previous value in the list. What I want is for the program to create an Alertdialog if no string value is entered in the TextField.
Here is my List (TaskData)
enter image description here
And my TextField
enter image description here
Try adding a errorText:
Full example
final _text = TextEditingController();
TextField(
controller: _text,
decoration: InputDecoration(
labelText: 'Enter the Value',
errorText: _validate ? 'Value Can\'t Be Empty' : null, //here
),
),
Inside a Button use:
bool _validate = false;
RaisedButton(
onPressed: () {
setState(() {
_text.text.isEmpty ? _validate = true : _validate = false;
});
},
child: Text('Submit')
textColor: Colors.white,
color: Colors.blueAccent,
),
try this in your addTask method
void addTask() {
if (name = '') showMyAlertDialog();
else {nameList.add(name);
notifyListeners();}
name = '';
}

How can I pass an async from page 1 to page 2, and execute the function in page 2 but display results on page 1?

I'm accessing a menu item which redirects me to a second page like so:
void handleClick(String value) {
switch (value) {
case 'Circles':
Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) => new CircleMaker()));
break;
On this second page, I have three TextFormFields as a StatefulWidget. They look like this:
new Container(
decoration: new BoxDecoration(
color: Colors.transparent,
backgroundBlendMode: BlendMode.colorBurn),
child: TextFormField(
controller: longitudeController,
cursorColor: Colors.white,
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
labelText: 'longitude',
))),
Lastly, I have this button on page 2:
FloatingActionButton(
child: Icon(Icons.lens),
backgroundColor: isPressed ? Colors.red : Colors.grey,
onPressed: () {
_makeCircles();
setState(() => isPressed = !isPressed);
},
)])
]),
)]));
}
}
The _makeCircles(); function is not defined/available in the page 2 build. But it's defined/available on page 1 and works perfectly. This is the function:
Set<Circle> circles;
Future<void> _makeCircles() async {
setState(() {
//work
]);
});
}
How can I grab this async function which is available on page 1, use it on page 2, and then be sent back to page 1 (which is a google map). To say this in another way, I want to enter my TextFormFields on page 2 and use them to plot a circle on page 1. Anybody know how to do this?
Create a function sendData in page2
sendData() async {
//Code to get location using Geolocator package.
return position;
}
In your page1,
Access sendData() function of page2 inside page1, to get your data.

Flutter TextField calls onSubmitted unexpectedly

My case is I have a widget with TextField used for search. When I type something in TextField the cross icon become visible in suffixIcon (to clear). I do not do search and just click the cross icon to clear the entered input but onSubmitted is called and search executed!!! But I don't need it! I do not submit the text input, I cancel it!!
final searchClear = ValueNotifier(false);
final searchController = TextEditingController();
// in initState method:
searchController.addListener(() {
searchClear.value = searchController.text.isNotEmpty;
});
// in build method:
TextField(
...
controller: searchController,
suffixIcon: ValueListenableBuilder<bool>(
valueListenable: searchClear,
builder: (_,visible,child) {
return Visibility(
visible: visible,
child:child,
);
},
child: InkWell(
child: Icon(Icons.close),
onTap: () {
searchController.clear();
searchFocus.unfocus();
}
),
),
onSubmitted: (value) {
if(value.isEmpty) {
FocusScope.of(context).requestFocus(searchFocus);
} else {
widget.search(value);
}
}
),
P.S. Any ideas to work around this?