i'm trying to supply an initial value however i keep getting errors. how do i approach this. stuff is a list of values by the way so it holds a list<map<string, dynamic>> function
Widget _buildDescriptionTextField(){
return Padding(
padding: const EdgeInsets.only(right: 30),
child: TextFormField(
decoration: InputDecoration(labelText: 'Description',),
initialValue: widget.stuff['description'],
maxLines: 4,
validator: (String? value){
//if (value!.length <= 0){ // use one or the other
if (value!.isEmpty || value.length < 10 ){ // (||) means or
return 'Description is required and should be 10+ characters';
}
},
onSaved: (String? value){
setState(() {
formData['description'] = value!;
// descriptionValue = value!;
});
},),
);
}
Here is the example for initial text in text field
class _FooState extends State<Foo> {
TextEditingController _controller;
#override
void initState() {
super.initState();
_controller = new TextEditingController(text: 'Initial value');
}
#override
Widget build(BuildContext context) {
return new Column(
children: <Widget>[
new TextField(
// The TextField is first built, the controller has some initial text,
// which the TextField shows. As the user edits, the text property of
// the controller is updated.
controller: _controller,
),
new RaisedButton(
onPressed: () {
// You can also use the controller to manipuate what is shown in the
// text field. For example, the clear() method removes all the text
// from the text field.
_controller.clear();
},
child: new Text('CLEAR'),
),
],
);
}
}
Related
I have a form that has three types of widgets such that DropDown, TextField, and TypeAhead. I have imported a package named flutter_typeahead that is basically a dynamic DropDown mixed with TextField.(More info about flutter_typeahead: flutter_typeahead, but there is no need to know flutter_typeahead widget to be able to understand and solve the problem.)
However, when I try to validate, if the TypeAhead widget is empty or null, then I throw an error to the user. Everything is ok up to now. But, when I fill the other instances of the form(DropDown and TextFields) and let the TypeAhead empty then the validation is not working. What I mean, If I fill the DropDowns and the TextFields and let the TypeAhead empty, then try to submit the form actually submits it. However, if I let the TextField empty or the DropDown as default the validation works fine.
To sum up, when all form widgets are empty, TypeAhead validation works, when only TypeAhead is empty it doesn't work.
Form widget
Form formWidget(Map<String, dynamic> map) {
return Form(
key: _formKey,
child: ListView(
shrinkWrap: true,
children: [
customTypeAhead(map['stajTuru'], _stajTuruController,
_selectedStajTuru, 'Staj Türü'), //Custom typeahead widget
customTypeAhead(
map['doktor'], _doktorController, _selectedDoktor, 'Doktor'), //Custom typeahead widget
customDropDown(
_valueOrtam, map['ortam'], hintTextOrtam, onChangedOrtam),
customDropDown(
_valueKapsam, map['kapsam'], hintTextKapsam, onChangedKapsam),
customDropDown(_valueEtkilesim, map['etkilesim'], hintTextEtkilesim,
onChangedEtkilesim),
customDropDown(_valueCinsiyet, map['cinsiyet'], hintTextCinsiyet,
onChangedCinsiyet),
const SizedBox(
height: 20,
),
customTextField(
1, "Kayıt No ", 10, _formData.setKayitNo, isEmpty, _kayit, 80),
customTextField(
1, "Hastanın Yaşı", 3, _formData.setYas, isNumeric, _yas, 80),
customTextField(
1, "Şikayet", 10, _formData.setSikayet, isEmpty, _sikayet, 80),
customTextField(1, "Ayırıcı Tanı", 10, _formData.setAyiriciTani,
isEmpty, _ayirici, 80),
customTextField(5, "Kesin Tanı", 50, _formData.setKesinTani, isEmpty,
_kesin, 130),
customTextField(5, "Tedavi Yöntemi", 200, _formData.setTedaviYontemi,
isEmpty, _tedavi, 130),
],
),
);
}
customTypeAhead
Widget customTypeAhead(List<String> listItems, TextEditingController controller,
String? stajTuru,String labelText) {
//check if the typed item is in the list
List<String> getSuggestions(String query) {
return List.of(listItems).where((item) {
final queryLower = query.toLowerCase();
final itemLower = item.toLowerCase();
return itemLower.contains(queryLower);
}).toList();
}
return Padding(
padding: const EdgeInsets.all(PADDING_VALUE),
child: Column(
children: [
Text(
labelText,
style: TEXT_STYLE,
),
TypeAheadFormField<String?>(
onSuggestionSelected: (String? val) =>controller.text = val!,
itemBuilder: (context, String? suggestion) {
return ListTile(
title: Text(suggestion!),
);
},
suggestionsCallback: getSuggestions,
validator: (value) { // This is my validation method
bool isInTheList=false;
for(var item in listItems){
if(item==value) {
isInTheList=true;
}
}
if (value == null || value.isEmpty || isInTheList==false) {
return 'Lütfen ${labelText.toLowerCase()} seçiniz';
} else {
print("null returned");
return null;
}
},
textFieldConfiguration: TextFieldConfiguration(
controller: controller,
decoration: const InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: TEXT_COLOR,
),
),
border: OutlineInputBorder(
borderSide: BorderSide(
color: TEXT_COLOR,
)))),
),
],
),
);
}
Submit function
void formIlet() async {
if (formArguments != null) {
if (_formKey.currentState!.validate()) {
setFormArgumentState();
bool res = await _mySqlHelper.insertData(formArguments!.formData);
if (res) {
_helper.update(formArguments!.formData);
customSnackBar(context, 'Başarıyla gönderildi');
} else {
errorAlert(context);
}
}
} else {
if (_formKey.currentState!.validate()) {
setFormDataState();
isLoading = true;
bool res = await _mySqlHelper.insertData(_formData).then((val) {
setState(() {
isLoading = false;
_formKey.currentState?.dispose();
});
return val;
});
if (res) {
customSnackBar(context, 'Başarıyla gönderildi');
} else {
errorAlert(context);
}
}
}
}
I have solved this problem. I don't know why it happened, but using a ListView inside the Form is not a good idea. That's causing the problem. So, I changed the ListView with a Column and wrapped it with SingleChildScrollView the problem is solved.
I am very new to flutter. I am trying to create List view with Dynamically generated DropDownButton & And Label .No matter what I do this error occurs and dropdown items not updating.
Expected a value of type 'List<DropdownMenuItem<String>>', but got one of type 'List<dynamic>'
This is my listview builder code
ListView.builder(
itemCount: tasksLength,
itemBuilder: (context, index) {
String roleId = taskRoles[index]['roleId'];
List<DropdownMenuItem<String>> _userList = [DropdownMenuItem<String>(value: '', child: Text('Loading..'))].toList();
if (usersList['roles'] != null && usersList['roles'][roleId] != null) {
_userList = usersList['roles'][roleId]['users'].map((item) {
return DropdownMenuItem<String>(value: item['id'],child: Text(item['name'].toString()));
}).toList();
}
return UserSelect(userList: _userList);
},
),
This is my widget class with the DropDownbutton
class UserSelect extends StatefulWidget {
List<DropdownMenuItem<String>>? userList =
[DropdownMenuItem<String>(value: '', child: Text('Loading..'))].toList();
UserSelect({this.userList});
#override
_UserSelectState createState() => _UserSelectState();
}
class _UserSelectState extends State<UserSelect> {
String _selected_user = '';
String _roleName = 'User Role';
List<DropdownMenuItem<String>> _userList =
[DropdownMenuItem<String>(value: '', child: Text('Loading..'))].toList();
#override
void initState() {
super.initState();
}
#override
void didUpdateWidget(UserSelect oldWidget) {
if (oldWidget.userList != widget.userList) {
_userList = widget.userList!;
}
super.didUpdateWidget(oldWidget);
}
#override
Widget build(BuildContext context) {
return Column(
children: [
Text(
_roleName,
style: TextStyle(
fontFamily: 'Bilo',
fontSize: 16,
color: const Color(0xff3b3e51),
letterSpacing: 0.224,
height: 1.5,
),
textHeightBehavior:
TextHeightBehavior(applyHeightToFirstAscent: false),
textAlign: TextAlign.left,
),
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(18.0),
color: const Color(0xfff6f6f6),
),
child: DropdownButton<String>(
isExpanded: true,
value: (_selected_user.length > 0) ? _selected_user : null,
icon: const Icon(Icons.keyboard_arrow_down),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.black45),
hint: new Text("Select User"),
underline: Container(
height: 2,
color: Colors.white24,
),
onChanged: (String? newValue) {
setState(() {
_selected_user = newValue!;
});
},
items: _userList),
)
],
);
}
}
Some of codes unnecessary I tried by best to skip this error that is why some junk codes are there.
Please help me to fix this issue or show me right direction.
I think the issue here is the .toList(); method calls here:
List<DropdownMenuItem<String>> _userList =
[DropdownMenuItem<String>(value: '', child: Text('Loading..'))].toList();
toList() in dart returns a list with the type that's supplied to its type parameter. Documentation
When not supplied with a type parameter, I would assume that the toList() method's return type is dynamic.
You can just remove the toList() method call altogether, as you already placed the DropDownMenuItem into a list by placing it between the [square brackets]! Ironically, the type would've been inferred by the list declaration before you overwrote it with toList() and made it dynamic :')
If you DO need to do it this way, you can simply add [items ...].toList<DropdownMenuItem>() which will correctly return a list of type DropdownMenuItem :)
I have two textfields that accept number inputs. I want to calculate the sum of the two textfields while the user input the numbers in the textfields and in realtime show the results in a third textfield. This is what I have tried so far.
void _calculation() {
setState((){
_total = int.parse(_quantityController.text) * int.parse(feedPrice.text);
},
);
print(_total);
}
And show the result in the third textfield
TextField(
readOnly: true,
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: _total.toString(),
),
),
I pass the total as a string to Textfield hint field. What am I missing or what am I doing wrong?
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class _YourPageState extends State<YourPage> {
int _age1 = 0, _age2 = 0, _totalAge = 0;
final firstNumber = TextEditingController();
final secondNumber = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(32.0),
child: Column(
children: <Widget>[
TextField(
controller: firstNumber,
textInputAction: TextInputAction.next,
keyboardType: TextInputType.number,
onSubmitted: (String value) {},
),
TextField(
controller: secondNumber,
textInputAction: TextInputAction.next,
keyboardType: TextInputType.number,
onSubmitted: (String value) {},
),
Text(
'Sum is: ${firstNumber.text + secondNumber.text}',
textAlign: TextAlign.center,
style: const TextStyle(fontWeight: FontWeight.bold),
)
],
),
),
);
}
}
you are doing wrong at setting hintText .Because hint Text that suggests what sort of input the field accepts.
you should set text to text field instead of hinttext like this
text:_total.toString()
Demo Widget
class ApplicantsX extends StatefulWidget {
const ApplicantsX({Key? key}) : super(key: key);
#override
State<ApplicantsX> createState() => _ApplicantsXState();
}
class _ApplicantsXState extends State<ApplicantsX> {
double a = 0;
double b = 0;
final TextEditingController controller = TextEditingController();
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Column(
children: [
TextField(onChanged: (value) {
final x = double.tryParse(value);
setState(() {
a = x ?? 0; // handle null and String
controller.text = (a + b).toStringAsFixed(2);
});
}),
TextField(onChanged: (value) {
final x = double.tryParse(value);
setState(() {
b = x ?? 0;
controller.text = (a + b).toStringAsFixed(2);
});
}),
TextField(
controller: controller,
readOnly: true,
)
],
);
}
}
After reset all textfield values and result when i enter a new number in any textfield that number is added to previous result so, can u plz give the code for previous result not considered.
I'm trying to change my icon after I tap on my List Item. I already tried different things: I tried the onTap method but the icon just does not want to change. I'm very new to flutter and I would love to find some help for my problem :). Here is my code.
I already searched for solutions but I didn't got it working in my project
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'To-Do List',
theme: ThemeData(
primaryColor: Colors.white,
brightness: Brightness.dark,
),
home: Scaffold(
appBar: AppBar(title: Text('To-Do List'),
backgroundColor: Colors.amber,
),
body: BodyLayout(),
),
);
}
}
class BodyLayout extends StatefulWidget {
#override
BodyLayoutState createState() {
return new BodyLayoutState();
}
}
class BodyLayoutState extends State<BodyLayout> {
// The GlobalKey keeps track of the visible state of the list items
// while they are being animated.
final GlobalKey<AnimatedListState> _listKey = GlobalKey();
// backing data
List<String> _data = [];
final _isdone = Set<String>();
// bool selected = false;
List<bool> selected = new List<bool>();
Icon notdone = Icon(Icons.check_box_outline_blank);
Icon done = Icon(Icons.check_box);
TextEditingController todoController = TextEditingController();
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
SizedBox(
height: 445,
child: AnimatedList(
// Give the Animated list the global key
key: _listKey,
initialItemCount: _data.length,
// Similar to ListView itemBuilder, but AnimatedList has
// an additional animation parameter.
itemBuilder: (context, index, animation) {
// Breaking the row widget out as a method so that we can
// share it with the _removeSingleItem() method.
return _buildItem(_data[index], animation);
},
),
),
TextField(
controller: todoController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'To-Do'
),
),
RaisedButton(
child: Text('Insert item', style: TextStyle(fontSize: 20)),
onPressed: () {
_insertSingleItem();
},
),
RaisedButton(
child: Text('Remove item', style: TextStyle(fontSize: 20)),
onPressed: () {
_removeSingleItem();
},
)
],
);
}
// This is the animated row with the Card.
Widget _buildItem(String item, Animation animation) {
final isdone = _isdone.contains(item);
selected.add(false);
return SizeTransition(
sizeFactor: animation,
child: Card(
child: ListTile(
title: Text(
item,
style: TextStyle(fontSize: 20),
),
trailing: Icon(
isdone ? Icons.check_box: Icons.check_box_outline_blank
),
onTap: (){
setState(() {
});
},
),
),
);
}
void _insertSingleItem() {
int insertIndex = 0;
setState(() {
_data.insert(0, todoController.text);
});
// Add the item to the data list.
// Add the item visually to the AnimatedList.
_listKey.currentState.insertItem(insertIndex);
}
void _removeSingleItem() {
int removeIndex = 0;
// Remove item from data list but keep copy to give to the animation.
String removedItem = _data.removeAt(removeIndex);
// This builder is just for showing the row while it is still
// animating away. The item is already gone from the data list.
AnimatedListRemovedItemBuilder builder = (context, animation) {
return _buildItem(removedItem, animation);
};
// Remove the item visually from the AnimatedList.
_listKey.currentState.removeItem(removeIndex, builder);
}
}```
You have already mentioned the icons above. You simply need to use them instead of declaring new ones again.
// This is the animated row with the Card.
Widget _buildItem(String item, Animation animation) {
final isdone = _isdone.contains(item);
selected.add(false);
return SizeTransition(
sizeFactor: animation,
child: Card(
child: ListTile(
title: Text(
item,
style: TextStyle(fontSize: 20),
),
trailing: isdone ? done: notdone, // use the icon variables you have already defined
onTap: (){
setState(() {
// add the item to _isdone set if it is not added and remove it if it is added when tapped on the list item
if(isdone) {
_isdone.remove(item);
} else {
_isdone.add(item);
}
});
},
),
),
);
}
In this code, I have added the item and removed the item in setSate() in the onTap(), so that whenever you tap the list item, _isdone Set gets updated and the build() is reloaded. Which makes your layout and data update itself every time you tap on the list item.
This is a flutter app using the stepper widget to display other widgets. I need to put two checkbox tile widgets in a row and which will be seperated by columns. I have initialized the checkbox tile widget but it keeps displaying a 'only static members can be accessed in initializers' for the onChanged and value parameters
class MyHome extends StatefulWidget {
#override
MyHomeState createState() => new MyHomeState();
}
class MyHomeState extends State<MyHome> {
void onChanged(bool value){
setState(() {
_isChecked = value;
});
}
static bool _isChecked = false;
// init the step to 0th position
int current_step = 0;
List<Step> my_steps = [
new Step(
// Title of the Step
title: new Text("Residential Data"),
// Content, it can be any widget here. Using basic Text for this example
content: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Activity"),
),
Row(
children: <Widget>[
Column(
children: <Widget>[
CheckboxListTile(value: _isChecked, onChanged: (bool value){setState(() {
_isChecked = value;
});})
],
),
Column(
children: <Widget>[
CheckboxListTile(value: _isChecked, onChanged: (bool value){onChanged(value);},)
],
)
],
),
Row(
children: <Widget>[
Column(
children: <Widget>[
CheckboxListTile(value: _isChecked, onChanged: (bool value){onChanged(value);})
],
),
Column(
children: <Widget>[
CheckboxListTile(value: _isChecked, onChanged: (bool value){onChanged(value);},)
],
)
],
)
],
),//new Text("Hello!"),
isActive: true),
new Step(
title: new Text("Step 2"),
content: new Text("World!"),
// You can change the style of the step icon i.e number, editing, etc.
state: StepState.editing,
isActive: true),
new Step(
title: new Text("Step 3"),
content: new Text("Hello World!"),
isActive: true),
];
#override
Widget build(BuildContext context) {
return new Scaffold(
// Appbar
appBar: new AppBar(
// Title
title: new Text("Simple Material App"),
),
// Body
body: new Container(
child: new Stepper(
// Using a variable here for handling the currentStep
currentStep: this.current_step,
// List the steps you would like to have
steps: my_steps,
// Define the type of Stepper style
// StepperType.horizontal : Horizontal Style
// StepperType.vertical : Vertical Style
type: StepperType.vertical,
// Know the step that is tapped
onStepTapped: (step) {
// On hitting step itself, change the state and jump to that step
setState(() {
// update the variable handling the current step value
// jump to the tapped step
current_step = step;
});
// Log function call
print("onStepTapped : " + step.toString());
},
onStepCancel: () {
// On hitting cancel button, change the state
setState(() {
// update the variable handling the current step value
// going back one step i.e subtracting 1, until its 0
if (current_step > 0) {
current_step = current_step - 1;
} else {
current_step = 0;
}
});
// Log function call
print("onStepCancel : " + current_step.toString());
},
// On hitting continue button, change the state
onStepContinue: () {
setState(() {
// update the variable handling the current step value
// going back one step i.e adding 1, until its the length of the step
if (current_step < my_steps.length - 1) {
current_step = current_step + 1;
} else {
current_step = 0;
}
});
// Log function call
print("onStepContinue : " + current_step.toString());
},
)),
);
}
}
You created your widget tree as a field of the class:
class Foo extends StatelessWidget {
String parameter;
Widget widget = Text(parameter); // only static members can be accessed in initializers
}
You shouldn't do this. You cannot initialize a field of an object with other class properties. Instead, create that widget inside the build method:
class Foo extends StatelessWidget {
String parameter;
#override
Widget build(BuildContext context) {
Widget widget = Text(parameter);
// TODO: do something width `widget`
}
}