Im using this package https://pub.dev/packages/pluto_menu_bar . I want to know do we have any easy way to add dynamic data and select them on tap,
when I had passed static data and its working fine but when larger data coming from the Database its not working
PlutoMenuItem(
title: 'Province',
children: [
PlutoMenuItem.checkbox(
title: 'Sindh',
initialCheckValue: false,
onChanged: (flag) {
flag == true
? provinceSelectedList.add("Sindh")
: provinceSelectedList.remove("Sindh");
},
),]
Related
I have a hive box opened in the main.dart and set it to a global variable so am able to access it from all other classes.
Now in one of my classes (settingsView.dart) which is a StatefulWidget am able to put data in the box in the form Map<String,Map<String,dynamic>>. To be specific the Map<String,dynamic> can be a Map<String,String> or Map<String,List>. e.g.
{"1A":{"num_on_roll": "34", "subjects": ["Mathematics","English","Science",...]}}
Now am also retrieving or reading this data and to display it in the UI the "num_on_roll" value in a Text widget and "subjects" value in a Wrap.
NOW THE PROBLEM.
The first ("num_on_roll") is always updated in the UI successfully but the "subjects" values in the Wrap are never updated unless I do hot restart or quit application and start it afresh, by so doing all data will be displayed successfully.
I have tried using ValueListenableBuilder to listen for changes in the box.
"class_constants" is the specific for the stored data which is Map<String,Map<String,dynamic>>.
ValueListenableBuilder(
valueListenable: Hive.box("mainDB").listenable(keys: ["class_constants"]),
builder: (context,Box box,child) {
var clsConst = box.get("class_constants", defaultValue: {});
return Wrap(
children: List.generate(
isPresent
? clsConst[classes[tab]]["subjects"].length
: selectedSubjects.length,
(index) => Text(
"${isPresent ? clsConst[classes[tab]]["subjects"][index] : selectedSubjects[index]}, ",
style: const TextStyle(
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic),
)),
);
}
),
Why is it that the data is store successfully but not displaying some part?
Please help me out.
I found the proper solution myself.
Hive has problem retrieving growable list immediately it has been put in the box. Even you must await it else it can't store!
So trick is to change growable list to non-growable list.
List list = [];
list.add(1);
list.add(2);
list.add(3);
// non-growable
List tempList = List.generate( list.length, (_)=> list[_], growable: false);
mainDB!.put('key',tempList)
;
I want to make an editable TextWidget in flutter but I don't really know how to go around it, I did some research, but still can't find a good solution.
Here's my sample code below.
I have a variable called
int qty = 1;
and so I called the variable in TextWidget
Column(
children: [
Text(
"${qty}",
style: TextStyle(),
)
],
),
I want to have these features that make user tab on the value to change it if they want, upon tap, a pop-up dialog will show to give the user the ability to change the existing value to whatever the user wants.
Please if anyone knows how, please help.
You will need a statfull widget to call setState and make the UI update with the new value stored in your qty variable. (I'am assuming that you are not using any state managment).
I wrote a possible solution for what you need.
Let look into some considerations:
Text will show whatever is in the qty as long we call setState after (or do it inside) we change the value of qty.
You need some widget to detect your tap. If you want to the text be 'clicable' then it should be wraped inside that widget.
The onTap/onPress call back of that widget should show a new widget. For this you can use the already made showDialog() and pass it a Dialog Widget. in here you will put your ui for that.
In some point of that UI you need to introduce the new value. So you can use a simple TextField that will save the introduced value, where you can assign it to qty, without forgetting to call setState! Note that it deal with strings, so you neet to do an int.parse() ou double.parse accordingly to you qty var type.
And I think that's it.
The could be other ways of doing it. This is a good and simple approach for your need.
I wrote a piece of code to help or somelse how is trying to do it:
InkWell(
// can be gesture detector, button, etc
onTap: () => showDialog(
context: context,
builder: (context) => Dialog(
child: Container(
color:
Colors.white60, // change it accordingly to you
height: 80, // change it accordingly to you
width: 200, // change it accordingly to you
child: Column(
children: [
const Text('Change your value here'),
TextField(
decoration:
InputDecoration(hintText: qty.toString()),
onChanged: (insertValue) => setState(() {
qty = int.parse(insertValue);
}),
// you can use other callBack function (like onComplete,
// onSaved), wich is more eficient than calling setState eveytime,
// but you have to do the needed adtaptions. Like onSave
// needs a key to call the save function. is easy just google it.
),
],
)),
)),
child: Text(
"${qty}",
),
),
What you are probably looking is a DropdownButton.
You would have something like this:
int qty = 1;
List<int> listOfValues = [1,2,3,4];
and then in your column you would have
DropdownButton<int>(
// This are the list of items that will appear in your dropdown menu.
// items is all the options you want your users to be able to select from,
// and it take a list of `DropdownMenuItem`. So instead of creating a `DropdownMenuItem`
// for each of the items in `listOfValues`, we iterate through it and return
// a `DropdownMenuItem`
items: listOfValues
.map((item) => DropdownMenuItem<int>(
value: item,
child: Text('$item'),
))
.toList(),
value: qty,
onChanged: (value) {
if (value != null) {
setState(() {
qty = value;
});
}
},
),
For more information on DropDownButton, check the following links:
https://api.flutter.dev/flutter/material/DropdownButton-class.html
https://www.youtube.com/watch?v=K8Y7sWZ7Q3s
Note: In a scenario where you want to increase the quantity of an item, like in a shopping cart, maybe having a button increment qty by 1 would be better.
I am using the flutter pref library to create a settings page. The PrefChoice is used to show a drop down for language selection. The drop down shows the values properly. Issue is when we select anything from the drop down, the onChange method does not get called for some reason. Due to this we are not able to take action on the change in choice. Is there anything I am missing here?
PrefChoice<String>(
title: Text(AppLocalization.of(context, 'settings.language')),
pref: 'language_key',
items: const [
DropdownMenuItem(
value: LocaleConstants.LC_ENGLISH,
child: Text(LocaleConstants.ENGLISH)),
DropdownMenuItem(
value: LocaleConstants.LC_GERMAN,
child: Text(LocaleConstants.GERMAN))
],
onChange: (value) {
// This never gets called
log.d('Locale changed to - $value');
},
),
How to use group button in listView ? In each row, it has two radio button.
The problem now is if I select one of the radio button , the radio button not showing it is selected.
int value;
Map<int, bool> answers = {};
String _radioValue;
String choice;
int count = 0;
...item['questions']
.asMap()
.entries
.map((items) {
count++;
return TableRow(children: [
Padding(
padding: EdgeInsets.all(10),
child: Text(items.value['name'])),
Row(
children: [
Radio(
value: items.value['id'],
groupValue: count,
onChanged: (val) {
setSelectedRadioTile(val);
},
),
Text("Yes"),
Radio(
value: items.value['id'] + count,
groupValue: count,
onChanged: (val) {
setSelectedRadioTile(val);
},
),
Text("N/A")
],
)
]);
}).toList()
setSelectedRadioTile(int val) {
print(val);
setState(() {
count = val;
});
}
Okay well I have built you a working version based on what you provided here. Please keep in mind that it would probably be a good idea to look at the documentation more in-depth so you get a feeling of how some widgets behave and what specific properties (like groupValue) are for. Also keep in mind that the following code is not optimised or whatsoever, I just got it worked out for your case - thinking about how to structure your data overall is some fundamental thing you should take a look at. Maybe try some out some flutter courses which are available or look at some youtube content from known flutter coders. But now back to some code stuff.
I used those properties in my StatefulWidget to work with. Since you use some kind of question map and I don't know how it looks like, I just used something bare bones:
/// Map which has the question ID as its key and the answer from the user (currently true for yes and false for no (or n/a as in your case)
Map<int, bool> _answers = {};
/// Map which holds the information of your questions. Right now only an ID to be able to reference it and the actual question - again very bare bones
Map<String, dynamic> _item = {
'questions': [
{
'id': 0,
'question': 'Is this legit?',
},
{
'id': 1,
'question': 'Oh really?',
},
]
};
Then the method which will be called by the Radio widget once onChanged is triggered:
/// We need to know which question has been answered (therefore the ID) and which (bool) answer has been clicked by the user
_setSelectedRadioTile(int id, bool answer) {
setState(() {
_answers[id] = answer;
});
}
And now the widget part - since your code starts where you iterate over the questions, I also share this part specifically:
/// Since the map itself is typed as <String, dynamic>, accessing 'questions' will return dynamic. Only we, as we know the structure, know that this is indeed a list. Therefore we need to cast this as "List<dynamic>" so we can iterate over it and won't get exceptions
(_item['questions'] as List<dynamic>)
.map(
(question) => TableRow(children: [
Padding(
padding: EdgeInsets.all(10),
child: Text(question['question'])),
Row(
children: [
Radio(
/// The [value] property of Radio tells us, which property is used in [onChanged] - therefore now once this Radio is clicked, true is provided in the [onChanged] callback
value: true,
/// [groupValue] is the value which this Radio is bound to. As you probably know, only one Radio button should be active for a group. So if you have a question which has several possible answers as radio buttons, we only want one of them to be active at a time. Thats what the [groupValue] is for. Since we iterate over all questions and every entity of a question (currently) has two possible answers (Yes and N/A), both those answers are for a specific question - the question with the current ID
groupValue: _answers[question['id']],
onChanged: (answer) {
_setSelectedRadioTile(question['id'], answer);
},
),
Text("Yes"),
Radio(
value: false,
groupValue: _answers[question['id']],
onChanged: (answer) {
_setSelectedRadioTile(question['id'], answer);
},
),
Text("N/A")
],
)
]),
)
.toList(),
This should work on your side once you updated this example to fit with your data model. Again: I advise you to think about how you structure your data generally.
My dropdown menu works properly after selecting a new option, but the new selection doesn't update the currently displayed option after its changed.
Widget buildCarDropdown() {
return
Center(
child: DropdownButton(
hint: Text('Please choose a car make'),
value: currentLease.carMake,
onChanged: (newValue) {
setState(() {
currentLease.carMake = newValue;
});
},
items: carMakes.map((String make) {
return DropdownMenuItem(
child: new Text(make),
value: make,
);
}).toList(),
),
);
}
carMakes is just an array of strings
currentLease contains a string for the selection of make. The value is set correctly after changing it in currentLease, and displays correctly if the widget is reloaded.
Everything seems proper here to me, not sure why it doesn't display updates properly.
Edit: What I mean by not updating it, that the drop down opens displaying all the options. Say it started at "Honda", you can then select "Acura" and though the currentLease.carMake gets updated properly, the drop down stays displaying "Honda" until it is reloaded.