I am new to Flutter development.
I want to retrieve data from a .json file (list of universities), and allow user to type the first letters so they can find their universities in the flutter drop down options.
The data I want to retrieve from the .json file is 'nom_court'.
My initial code is a textfield, and it's working perfectly :
TextFormField buildUniFormField() {
return TextFormField(
keyboardType: TextInputType.uni,
onSaved: (newValue) => uni = newValue,
onChanged: (value) {
if (value.isNotEmpty) {
removeError(error: kEmailNullError);
} else if (emailValidatorRegExp.hasMatch(value)) {
removeError(error: kInvalidEmailError);
}
return null;
},
validator: (value) {
if (value.isEmpty) {
addError(error: kEmailNullError);
return "";
} else if (!emailValidatorRegExp.hasMatch(value)) {
addError(error: kInvalidEmailError);
return "";
}
return null;
},
decoration: InputDecoration(
labelText: "University",
hintText: "Enter your university name",
floatingLabelBehavior: FloatingLabelBehavior.always,
suffixIcon: CustomSurffixIcon(svgIcon: "assets/icons/uni.svg"),
I am now trying to use a dropdownlist, using the .json file, and put this directly in the widget code :
#override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
buildEmailFormField(),
SizedBox(height: getProportionateScreenHeight(30)),
buildUniFormField(),
DropdownButton<String>(
items:list.map((Map val){
return DropdownMenuItem<String>(
value: val["Uniname"],
child: new Text(val["nom_court"]),
);).toList(),},
It's not working, I have an error on the 'Dropdown Button, saying 'The parameter Onchanged isn't defined'
Thanks :)
use autocomplete_textfield: ^1.6.4 package it would better option than a dropdown widget
https://medium.com/flutter-community/implementing-auto-complete-search-list-a8dd192bd5f6
So, it's just like your error message says, you haven't provided onChanged parameter to your DropdownButton.
You should create a state for current dropdown value and setState it in onChanged callback () for current dropdown value and setState it in onChanged callback:
class MyWidgetState extends State<MyWidget> {
String dropdownValue = // here specify the initial value for DropdownButton
Widget build(...) {
//...
DropdownButton(
value: dropdownValue,
onChanged: (value) => setState(() => dropdownValue = value),
items: list.map(...),
),
}
}
I assume you are already using StatefulWidget, if not please read the documentation
Related
I have get an index here but I want display it from first to last in image : I want to display "hello" first then the rest
code:
StreamBuilder(
stream: FirebaseFirestore.instance
.collection("groups")
.doc(groupId)
.snapshots(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
var chats = snapshot.data?["chats"];
return ...)};
ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: chats.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return Text(chats[index]),
}),
Basically I want to display the recently added string first.
You have to reverse: ture in your listView,
like this:
ListView.builder(
reverse:true,
physics: const BouncingScrollPhysics(),
itemCount: chats.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return Text(chats[index]),
}),
I did somehow managed to get the database contents to show via listview. However, its not doing it properly. As soon as i run the emulator the contents stored in the database should appear, but they don't. It also shows that the database is empty even though it clearly isn't. But once i add a new item to the database and click save, everything shows up (except the one i last added and it shows up on the next update). I have no clue how to fix this, i tried placing _listTodos() everywhere to see if it executes before the widgets but there wasn't any improvement. The issue is in the ListDisplay class I think, so you can just skip over the rest, I just have the entire code for convenience.
import 'package:flutter/material.dart';
import 'model/todo_model.dart';
import 'model/todo.dart';
class ListGradesPage extends StatefulWidget {
final String title;
ListGradesPage({this.title, Key key}) : super(key: key);
_ListGradesPageState createState() => _ListGradesPageState();
}
var _todoItem;
var _lastInsertedId = 0;
final _model = TodoModel();
Future<void> _deleteTodo() async {
_model.deleteAllTodo();
}
class _ListGradesPageState extends State<ListGradesPage> {
//final _model = TodoModel();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: <Widget>[
IconButton(
icon: Icon(Icons.edit),
onPressed: () {
print('editing...');
//_listTodos();
}),
IconButton(
icon: Icon(Icons.delete),
onPressed: () {
print('deleting all...');
setState(() {
_deleteTodo();
});
}),
],
),
body: ListDisplayPage(),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => AddGrade()),
);
},
child: Icon(Icons.add),
backgroundColor: Colors.blue,
),
);
}
}
class ListDisplayPage extends StatefulWidget {
ListDisplay createState() => ListDisplay();
}
class ListDisplay extends State<ListDisplayPage> {
int _selectedIndex;
List<Todo> todos = new List<Todo>();
Future<void> _listTodos() async {
todos = await _model.getAllTodos();
if (todos.isEmpty) {
print('it is empty-2.');
} else {
print("not empty-2");
}
print('To Dos:');
for (Todo todo in todos) {
print(todo);
}
}
_onSelected(int index) {
_selectedIndex = index;
}
#override
void initState() {
super.initState();
_listTodos();
// _listTodos() is not calling the function above for some reason, but executes everything below it
// In the database there are items stored however it says the databse is empty...
// until i add a new item and everything shows up except the item i recently added
if (todos.isEmpty) {
print('To Dos:');
for (Todo todo in todos) {
print(todo);
}
print('it is empty.');
} else {
print("not empty");
}
}
#override
Widget build(BuildContext context) {
//Color clr = Colors.transparent;
return todos.isEmpty
? Center(
child: Text(
'Nothing to show! Is it empty? ' + (todos.isEmpty).toString()))
: ListView.builder(
itemCount: todos.length,
itemBuilder: (context, index) {
return Card(
// <-- Card widget
child: Container(
color: _selectedIndex != null && _selectedIndex == index
? Colors.lightBlueAccent
: Colors.transparent,
child: ListTile(
leading: GestureDetector(
onTap: () {
setState(() {
_onSelected(index);
print(index);
});
},
child: Container(
width: MediaQuery.of(context).size.width / 2,
child:
Text(todos[index].sid + '\n' + todos[index].grade),
),
),
),
),
);
},
);
}
}
class AddGrade extends StatelessWidget {
String _sid, _grade;
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Add Grade"),
),
body: Form(
key: _formKey,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(15.0),
child: TextFormField(
decoration: const InputDecoration(
hintText: 'Student ID',
labelText: 'SID',
),
onSaved: (String value) {
print('Saving SID $value');
_sid = value.toString();
},
),
),
Padding(
padding: const EdgeInsets.all(15.0),
child: TextFormField(
decoration: const InputDecoration(
hintText: 'Student Grade',
labelText: 'Grade',
),
onSaved: (String value) {
print('Saving Grade $value');
_grade = value.toString();
},
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_formKey.currentState.save();
_addTodo();
//_listTodos();
Navigator.pop(context);
},
child: Icon(Icons.save),
backgroundColor: Colors.blue,
),
);
}
Future<void> _addTodo() async {
Todo newTodo = Todo(sid: _sid, grade: _grade);
_lastInsertedId = await _model.insertTodo(newTodo);
}
}
Console Output (on execution):
Restarted application in 1,607ms.
I/flutter (14196): To Dos:
I/flutter (14196): it is empty.
I/flutter (14196): not empty-2
I/flutter (14196): To Dos:
I/flutter (14196): Todo{id: 1, sid: q, grade: qq}
I/flutter (14196): Todo{id: 2, sid: w, grade: ww}
I/flutter (14196): Todo{id: 3, sid: e, grade: ee}
I/flutter (14196): Todo{id: 4, sid: r, grade: }
I/flutter (14196): Todo{id: 5, sid: hh, grade: kk}
Screenshots of emulator, before adding new student, and after adding new student (the recent one doesn't show up either until I add another student again),
Before
After
I apologize if i didn't follow the guidelines, never really posted questions on here before.
Are you aware of FutureBuilder? I would suggest wrapping your ListView.builder in a future builder and passing in the _loadTodos function as the future. Then you can remove all of the initState code that initializes the todos.
Generally, I find that doing async work in initState doesn't always work. The UI has already built, and doesn't know to rebuild when the async work is complete. Another option might just be to call setState once the async function completes with the todos. I would think that the FutureBuilder is the better way to do it though.
If you need some additional help, let me know. I could probably write some of it out for you.
I have a ChoicePrompt with two options.
[ {
value: 'credit',
synonyms: ['titanium', 'world', 'credit', 'mastercard'],
},
{
value: 'visaPrepaid',
synonyms: ['platinium', 'visa', 'prepaid', 'prepaid card', 'visa prepaid']
},]
The user can either click on the suggested action or type directly on the textbot "I want a credit card"
I wish to run on a Luis query recognition on this text and extract whether the user wanted a credit or a prepaid card. However, I don't know how to interect that string.
I use a WaterfallDialog to show the prompt
There are a couple different ways to build a ChoicePrompt. I use ChoiceFactory.forChannel() to do so. I'm then using imBack which returns the choice as a user text input. Alternatively, you could do a postBack, which would act as more of a trigger, and capture the sent value.
In my case, since the choice is returned as a user text input, I grab the text value from the activity and send that to LUIS. I'm matching on the Greeting intent which, if successful, then returns the intent found.
Hope of help!
async choiceStep ( stepContext ) {
const stepResult = stepContext.context.activity.text;
if ( stepResult ) {
const message = ChoiceFactory.forChannel(
stepContext.context, [
{ value: 'Hello', action: { type: 'imBack', title: 'Hello', value: 'Hello' } },
{ value: 'What is the date?', action: { type: 'imBack', title: 'What is the date?', value: 'What is the date?' } }
], `Which do you choose?`
);
await stepContext.context.sendActivity( message );
}
return { status: DialogTurnStatus.waiting };
}
async choiceLuisStep ( stepContext ) {
if ( stepContext.context.activity.text ) {
const stepResults = stepContext.context.activity.text;
await stepContext.context.sendActivity( `You said: ${ stepResults }` );
const recognizerResult = await this.recognizer.recognize( stepContext.context );
let intent = await LuisRecognizer.topIntent( recognizerResult );
if ( intent === 'Greeting' ) {
await stepContext.context.sendActivity( `Luis recognized: ${ intent }` );
return stepContext.next();
} else {
await stepContext.context.sendActivity( 'No LUIS intent was found.' );
return stepContext.next();
}
} else {
await stepContext.context.sendActivity( 'Thanks for visiting!' );
return stepContext.next();
}
}
I am new to Flutter and Dart. I have some data from an api json based and the variable of the data is called data. I have taken this sample code from the official flutter documentation and i want to be able to use the data variable and replace the string text, like so:
return new Card(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: const Icon(Icons.album),
title: const Text(data[index]['name']),
subtitle: const Text('Music by Julie Gable. Lyrics by Sidney Stein.'),
),
new ButtonTheme.bar( // make buttons use the appropriate styles for cards
child: new ButtonBar(
children: <Widget>[
new FlatButton(
child: const Text('BUY TICKETS'),
onPressed: () { /* ... */ },
),
new FlatButton(
child: const Text('LISTEN'),
onPressed: () { /* ... */ },
),
],
),
),
],
),
);
But I am getting an error on line title: const Text(data[index]['name']), and the error says Argument of type constant creation must be constant expression. This error it's coming from the Android Studio itself (version 3.2)
But when i use this code (taken from youtube course) it is working fine:
return new Container(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new Card(
child: new Padding(
padding: const EdgeInsets.all(16.0),
child: new Container(
child: Text(data[index]['name'],
style: TextStyle(
fontSize: 16.0, color: Colors.black54))),
)),
new Card(
child: new Padding(
padding: const EdgeInsets.all(16.0),
child: new Container(
child: Text(data[index]['description'],
style: TextStyle(
fontSize: 16.0, color: Colors.redAccent)),
)),
)
],
),
);
How to use the first code example without getting any errors? Thanks!
UPDATE: Here is the full code
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or press Run > Flutter Hot Reload in IntelliJ). Notice that the
// counter didn't reset back to zero; the application is not restarted.
primarySwatch: Colors.green,
),
home: new MyHomePage(title: 'Flutter App'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List data;
Future<String> getData() async {
http.Response response = await http.get(
Uri.encodeFull('https://dummyapicall.api'),
headers: {
"Accept": "application/json",
}
);
this.setState(() {
data = json.decode(response.body);
});
return 'Success!';
}
#override
void initState() {
super.initState();
this.getData();
}
#override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new ListView.builder(
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, int index) {
// return new Container(
// child: new Column(
// crossAxisAlignment: CrossAxisAlignment.stretch,
// children: <Widget>[
// new Card(
// child: new Padding(
// padding: const EdgeInsets.all(16.0),
// child: new Container(
// child: Text(data[index]['name'],
// style: TextStyle(
// fontSize: 16.0, color: Colors.black54))),
// )),
// new Card(
// child: new Padding(
// padding: const EdgeInsets.all(16.0),
// child: new Container(
// child: Text(data[index]['description'],
// style: TextStyle(
// fontSize: 16.0, color: Colors.redAccent)),
// )),
// )
// ],
// ),
// );
return new Card(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: const Icon(Icons.album),
title: const Text(data[index]['name']),
subtitle: const Text('Music by Julie Gable. Lyrics by Sidney Stein.'),
),
new ButtonTheme.bar( // make buttons use the appropriate styles for cards
child: new ButtonBar(
children: <Widget>[
new FlatButton(
child: const Text('BUY TICKETS'),
onPressed: () { /* ... */ },
),
new FlatButton(
child: const Text('LISTEN'),
onPressed: () { /* ... */ },
),
],
),
),
],
),
);
},
),
// floatingActionButton: new FloatingActionButton(
// onPressed: _incrementCounter,
// tooltip: 'Increment',
// child: new Icon(Icons.add),
// ), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
As your Text widget is defined as const the label or the properties of the widget should also be const, as your data is dynamic not a const at the compile time itself you will be shown the error.
Const Widget must be created from data that can be calculated at compile time. A const object does not have access to anything you would need to calculate at runtime. 1 + 2 is a valid const expression, but new DateTime.now() is not.
From : More about Const, Static, Final
Just remove the const keyword in both places of the ListTile.
They can't be constant as you are including a variable (data) inside the Text widget.
children: <Widget>[
ListTile(
leading: const Icon(Icons.album),
title: Text(data[index]['name']),
subtitle: const Text(
'Music by Julie Gable. Lyrics by Sidney Stein.'),
),
.....
I am new to flutter, I want to dismiss my dialog after the task completion. I've tried with:
Navigator.pop(context, true);
But my screen is getting black and dialog is still up there. here is my dialog code.
Dialog _dialog = new Dialog(
child: new Row(
mainAxisSize: MainAsixSize.min,
children: <Widget> [
new CircularProgressIndicator(),
new Text("Loading")]),
);
https://docs.flutter.io/flutter/material/showDialog.html says
The dialog route created by this method is pushed to the root navigator. If the application has multiple Navigator objects, it may be necessary to call Navigator.of(context, rootNavigator: true).pop(result) to close the dialog rather just Navigator.pop(context, result).
so I'd assume one of these two should do what you want.
This code works for me:
BuildContext dialogContext;
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
dialogContext = context;
return Dialog(
child: new Row(
mainAxisSize: MainAxisSize.min,
children: [
new CircularProgressIndicator(),
new Text("Loading"),
],
),
);
},
);
await _longOperation();
Navigator.pop(dialogContext);
If you don't want to return any result after showDialog is closed, you can use
Navigator.pop(context);
If you want to pass result call
Navigator.pop(context, result);
Example:
showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: Text('Wanna Exit?'),
actions: [
FlatButton(
onPressed: () => Navigator.pop(context, false), // passing false
child: Text('No'),
),
FlatButton(
onPressed: () => Navigator.pop(context, true), // passing true
child: Text('Yes'),
),
],
);
}).then((exit) {
if (exit == null) return;
if (exit) {
// user pressed Yes button
} else {
// user pressed No button
}
});
//it work conrrectly
onPressed: () {
Navigator.of(context, rootNavigator: true).pop();
},
Generally Navigator.pop(context); works.
But If the application has multiple Navigator objects and dialogBox doesn't close, then try this
Navigator.of(context, rootNavigator: true).pop();
If you want to pass result call, try
Navigator.pop(context,result);
OR
Navigator.of(context, rootNavigator: true).pop(result);
Better to use Completer, because if your operation is too short or the device is too slow, then the dialogContext variable will not be initialized and you can't close the dialog.
final dialogContextCompleter = Completer<BuildContext>();
showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext dialogContext) {
if(!dialogContextCompleter.isCompleted) {
dialogContextCompleter.complete(dialogContext);
}
return AlertDialog(
content: CircularProgressIndicator(),
);
},
);
// Close progress dialog
final dialogContext = await dialogContextCompleter.future;
Navigator.pop(dialogContext);
This will close dialog/alert box
Navigator.of(context).pop();
showDialog(
context: context,
builder: (BuildContext context) => Center(
child: CircularProgressIndicator(),
),
);
await Future<int>.delayed(Duration(seconds: 3));
Navigator.of(context, rootNavigator: true).pop();
Add on to Günter's answers. If you need to dismiss it when the user clicks elsewhere
change this property to true
barrierDismissible: true,
Try this. It will definitely work. use the context of pageBuilder in Navigator to pop the dialog from screen.
showGeneralDialog(
context: context,
barrierLabel: "XYZ",
barrierDismissible: true,
barrierColor: Colors.black.withOpacity(0.7),
pageBuilder: (dialogContext, __, ___) {
return Center(
child: Container(
height: 240,
margin: const EdgeInsets.symmetric(horizontal: 15),
decoration: bd,
child: SizedBox.expand(
GestureDetector(
onTap: (){
Navigator.pop(dialogContext);
},
child: const Padding(
padding: EdgeInsets.fromLTRB(10,0,10,0),
child: Icon(Icons.close, size: 26, color:Colors.white),
),
),
)
)
);
}
);