Flutter dropdown stopped showing selected value - flutter

I have a stateful class with this function:
recordSelectedTime(DateTime? selectedTime){
if (selectedTime!=null && kDebugMode) print('Received time: ${DateFormat('hh:mm a').format(selectedTime)}');
setState(() {
time = selectedTime?? DateTime.now(); **// THIS UPDATES TIME**
});
if (selectedTime == null) {
Provider.of<CP>(context, listen: false).getOrder().prefTime = null;
} else {
Provider.of<CP>(context, listen: false).getOrder().prefTime = selectedTime.millisecondsSinceEpoch;
}
}
In my class, I then create a stateless widget and pass this function as a callback function:
TimeSelection(mode: Provider.of<CP>(context).getDeliveryMode(), callBack:recordSelectedTime , def: time,),
Then in my stateless widget there is a dropdown button as below, this used to work before, as in when new value is selected it shows the new value, but then it has stopped working for some reason (flutter upgrade may be?). Now when I select the new value from the dropdown, I have the old same value displayed even after the selection. Although I have confirmed that my callback is working fine with debug statements. Any idea as to what has changed? thanks
child: DropdownButton(
isExpanded: true,
dropdownColor: Colors.white,
items: options,
hint: def.difference(DateTime.now()).inMinutes<3? Text('ASAP (As soon as possible)', style: TextStyle(color: Colors.green),) : Text(DateFormat('hh:mm a').format(def), style: TextStyle(color: Colors.green)),
onChanged: (value) => callBack(value as DateTime),
),

Related

Flutter TextFormfield Controller get value

This is Textformfield. It receives the value and then displays the information through it. TextEditContoller
This is page 1
Widget lngTextFormField(String label, String keyword, String text) {
TextEditingController lngtextController = TextEditingController(text: text);
lngtextController.selection = TextSelection.collapsed(offset: lngtextController.text.length);
return TextFormField(
controller: lngtextController,
onChanged: (value) {
saveAd(value, keyword);
},
decoration: InputDecoration(
labelText: label,
labelStyle: TextStyle(
fontFamily: 'supermarket',
fontSize: 16,
),
isDense: true,
),
);
}
This is a page 2
This is a save button that will return lat,lng to page 1.
void saveAddress() {
var lat = centerMap.latitude;
var lng = centerMap.longitude;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditAddressPage(
index: widget.index,
lat: lat.toString(),
lng: lng.toString(),
),
),
);
print("Saving address: Latitude: $lat, Longitude: $lng");
}
what can i do I want to send the second page lat,lng values ​​back to page 1 instead of the existing values. I tried this, sometimes the value is sent but the original value is empty before the new value is sent. Maybe need to type something in TextFormfield before being able to save
There are a lot of option to do, but the one of the easiest is :
When navigates to 2nd page from 1st page, replace or pop it
//you can use this
Navigator.pushReplacement(context, route);
//or this
Navigator.of(context).push(MaterialPageRoute(builder: (context) => NewScreen()));
Navigator.pop(context);
after 2nd page open and button pressed, you need to pass string to 1st page using Navigator.push (you have done it well)
inside initstate of the 1st page make a condition, example
#override
void initState() {
super.initState();
if (widget.lat != null || widget.lat != "") {
lattextController.text = widget.lat!;
}
if (widget.lng != null || widget.lng != "") {
lngtextController.text = widget.lng!;
}
//sometime when initsate doesnt work you can call setstate, depends on logic that you writes
}
this logic means that when the 1st page created they will set the value first before build()

Why DropdownButtonFormField Wrapped with FutureBuilder Being Rebuilt with Same Data Appended?

I have created a Flutter stateless dropdown widget that is dependent on some future list, I used the FutureBuilder to build the dropdown as soon as the future is resolved.
But I noticed that build method was being called at least twice. I know it is normal that the build method can be called multiple times when some state changes, but why was the dropdown was being rebuilt with the same data as the previous build call? I thought for sure when build is called, Flutter will rebuild the entire widget which also implies that the previous data will be destroyed as well.
This has resulted in duplication in the items of the dropdown.
I am not sure why it is happening. What did I miss?
class _PetTypeInput extends StatelessWidget {
#override
Widget build(BuildContext context) {
final petTypes = context.read<RegisterPetProfileCubit>().getPetTypes();
return FutureBuilder<List<PetType>>(
future: petTypes,
builder: (BuildContext context, AsyncSnapshot<List<PetType>> snapshot) {
List<PetType>? petKinds = [];
if (snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) {
petKinds = snapshot.data;
return DropdownButtonFormField<String>(
key: const Key('registerForm_petKindInput_dropdownButtonFormField'),
decoration: const InputDecoration(
labelText: 'pet kind',
helperText: '',
errorText: null,
),
value: 'Dog',
onChanged: (petKindValue) => context
.read<RegisterPetProfileCubit>()
.petKindChanged(petKindValue!),
items: _buildItems(petKinds),
);
}
return const TextField(
enabled: false,
keyboardType: TextInputType.name,
decoration: InputDecoration(
labelText: 'pet kind',
helperText: '',
),
);
},
);
}
List<DropdownMenuItem<String>> _buildItems(List<PetType>? petKinds) {
final petTypes = petKinds!.fold(
<String, String>{},
(Map<String, String> petTypesMap, petType) {
petTypesMap[petType.id] = petType.label;
return petTypesMap;
},
);
List<String> items = petTypes.keys.toList();
return items.map((key) {
return DropdownMenuItem<String>(
key: Key(key),
child: Text(petTypes[key]!),
value: key,
);
}).toList();
}
}
I can definitely tell that there are no duplicates in the data.
How do I prevent appending the same data? Or clear the previous data of DropdownButtonFormField?
You can build _buildItems(petKinds), before return DropdownButtonFormField<String>( and passing item[0] value on DropdownButtonFormField value. And it will make sure the value contain on DropDownMenuItems. Also, make sure to have Unique value on each DropDownMenuItem.
I finally figured it out. The issue is not duplicate dropdown items but rather my initial value is not a valid value. My initial value was Dog when it should be the id of the Dog item.
So I grabed the first item object and then grabed the id of that item and supplied it as initial value.
The answers from this question helped me figured it out.

Flutter : onSaved event not fired after selected item in MultiSelect

I am using Flutter Multiselect from official - flutter_multiselect: ^0.5.1
everything works fine , but onSaved() event not fired after selecting/deselecting and clicking the save button in MultiSelect Widget. i just wanna print the selected/deselected item in console.
Note : am also trying to get via change() event , its works only if we selecting the option, not works while deselcting.
help me to resolve this problem
Sample Code:
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
),
alignment: Alignment.center,
child: new MultiSelect(
maxLength: 1,
maxLengthText: "",
autovalidate: false,
dataSource: countries,
textField: 'country_name',
valueField: 'country_id',
hintText: "Select Your Country",
initialValue: countryID,
value: countryID,
required: true,
validator: (value) {
if (value == null) {
return 'Please Select Country';
}
},
filterable: true,
change: (values) {
if (values != null) {
setState(() {
countryID = values.cast<String>();
getStatesByCountry();
});
}
//this event emitted while selecting option from multiselect
//not works on deselecting option from multiselect
},
onSaved: (value) {
debugPrint("on save event");
print(value);
//always not emitting
},
),
)
Since I cannot see whole code, it's hard to tell but I would guess you don't save the whole form like this:
void _onFormSaved() {
final FormState form = _formKey.currentState;
form.save();
}
I would recommend to follow this original example
Hope it somehow help. Cheers
i dont know its a correct way, but in my case just cleaned a build and reinstalled packge will emit onchange event while removing items in multiselect,nothing else works me

How do I make DropdownButtonFormField show me the output that is the value that I have saved in my database

I am working with a DropdownButtonFormField and so far the list is loading me, but I would like you to load the list and also load the item that is saved in my database and show it to me as output indicating that the user had already selected an item previously.
This is the code that I am using
DropdownButtonFormField(
isDense: true,
//hint: new Text("Seleccione Barrio"),
items: dataBarrio.map((item) {
return new DropdownMenuItem(
child: new Text(item['nom']),
value: item['id'].toString(),
);
}).toList(),
onChanged: (newVal) {
setState(() {
_mySelectionBarrio = newVal;
});
},
value: _mySelectionBarrio,
)

Flutter- TextEditingController listener get called multiple time for textfield

TextField controlled controller.addListener(() gets called multiple time after pressing the clear button, this will only happen if we are clearing it.
Snippet:
TextEditingController controller = new TextEditingController();
TextField field = new TextField(
controller: controller,
autofocus: true,
);
controller.addListener(() {
print("Pressed cancel button");
});
Video Link
Note: While adding characters in TextField listener method gets called only ones.
I guess that would be a defect on flutter, a possible solution would be to use onChanged()
TextField field = new TextField(
autofocus: true,
onChanged: (String value) {
print("Pressed clear button");
},
);
I have the same problem with Nexus 6p when used with API level 23 and Pixel with API 25.
but this problem did not occurs with Pixel with API28 and it does not occurs with Nexus6P with API26.
exact code from https://flutter.dev/docs/cookbook/forms/text-field-changes was used.
1. We need to create our own .clear() method
void clearField() {
print("c: clearField");
var newValue = textController.value.copyWith(
text: '',
selection: TextSelection.collapsed(offset: 0),
);
textController.value = newValue;
callApi('');
}
// and call it by :
child: TextField(
controller: textController,
autofocus: true,
decoration: InputDecoration(
suffixIcon: IconButton(
icon: Icon(Icons.close),
onPressed: clearField, // call
),
),
),
2. We need to carefully handle changes
void changesOnField() {
print("c: changesOnField");
String text = textController.text;
if (text.isNotEmpty) { // set this
callApi(text);
}
}
Full Code
You may look into this repo and build it locally Github
Result