Flutter textformfield auto de-focus - mobile

This is the function I'm using to get a form displayed on my screen.
Form getNewLoanForm() {
return new Form(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new TextFormField(
decoration: new InputDecoration(labelText: 'Loan name'),
validator: (value) {
if (value.isEmpty) {
return 'Enter name';
} else {
return null;
}
},
onSaved: (value) => _loanName = value,
),
new Container(height: 16.0),
new RaisedButton(
child: new Text(
'ADD',
style: new TextStyle(color: Colors.white, fontSize: 17.0),
),
onPressed: addNewLoan,
color: Colors.blue,
)
],
),
);
}
Everything works fine up unit now. The problem starts when I add
final formKey = new GlobalKey<FormState>();
I declare this varial in class level. and use it in form.
return new Form(
key: formKey,
Like this and now the TextFormField starts to behave weirdly. Now if I select the text field it deselects itself.
Now keep in mind that this doesn't happen if I make this page my root page. But I'm pushing this page from my root page. If I make this page my root page the problem doesn't occur there.
Any idea what's wrong here?
Okay I'm putting my whole class
import 'package:flutter/material.dart';
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
import 'package:intl/intl.dart';
class NewLoan extends StatelessWidget {
String _loanName;
String _dateCreated;
final formKey = new GlobalKey<FormState>();
void addNewLoan() {}
Form getNewLoanForm(BuildContext context) {
final dateFormat = DateFormat("dd/MM/yyyy");
return new Form(
// key: formKey,
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new TextFormField(
decoration: new InputDecoration(labelText: 'Loan name'),
validator: (value) {
if (value.isEmpty) {
return 'Enter name';
} else {
_loanName = value;
return null;
}
},
),
new Container(height: 16.0),
DateTimePickerFormField(
decoration: new InputDecoration(labelText: 'Date'),
format: dateFormat,
dateOnly: true,
onChanged: (date) {
print('Selected date ${date.toString()}');
Scaffold
.of(context)
.showSnackBar(SnackBar(content: Text('$date')));
},
),
new Container(height: 16.0),
new RaisedButton(
child: new Text(
'ADD',
style: new TextStyle(color: Colors.white, fontSize: 17.0),
),
onPressed: addNewLoan,
color: Colors.blue,
)
],
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text('New Loan'),
),
body: new Container(
padding: new EdgeInsets.all(20.0),
child: getNewLoanForm(context),
),
);
}
}
My Root page
import 'dart:async';
import 'package:firebase/new_loan.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'auth.dart';
import 'current_balance_page.dart';
import 'dart:io' show Platform;
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';
class HomePage extends StatefulWidget {
HomePage({this.auth, this.onSignOut});
final BaseAuth auth;
final VoidCallback onSignOut;
#override
_HomePageState createState() => _HomePageState();
}
FirebaseApp app;
Future<FirebaseApp> firebaseApp() async {
final FirebaseApp app = await FirebaseApp.configure(
name: 'hisab-442a2',
options: Platform.isIOS
? const FirebaseOptions(
googleAppID: '1:18726312:ios:1b7829f2ac180d28',
gcmSenderID: '75461431231231291692',
databaseURL: 'https://hisab-44s2a2.firebaseio.com',
)
: const FirebaseOptions(
googleAppID: '1:297855924061:android:669871c998cc21bd',
apiKey: 'AIzaSyD_shO5mfO9lhy2TVWhfo1VUmARKlG4suk',
databaseURL: 'https://hisab-442a2.firebaseio.com',
),
);
return app;
}
enum Balancestatus { checking, found, noBalance }
class _HomePageState extends State<HomePage> {
Balancestatus status = Balancestatus.checking;
DatabaseReference _databaseRef;
#override
void initState() {
super.initState();
getDatabaseRef();
}
void getDatabaseRef() async {
app = await firebaseApp();
final FirebaseDatabase database = new FirebaseDatabase(app: app);
_databaseRef = database.reference();
_databaseRef.child('ccurrent_balance').once().then((DataSnapshot snapshot) {
print('Current balance ${snapshot.value}');
int balance = snapshot.value;
setState(() {
if (balance == null || balance == 0) {
status = Balancestatus.noBalance;
} else {
status = Balancestatus.found;
}
});
});
}
Future _signOut() async {
try {
await widget.auth.singOut();
widget.onSignOut();
} catch (e) {
print('Error signing out: $e');
}
}
void balanceSet() {
setState(() {
status = Balancestatus.checking;
});
}
#override
Widget build(BuildContext context) {
switch (status) {
case Balancestatus.checking:
return new WelcomePage(onSignOut: _signOut);
case Balancestatus.found:
// return new NewLoan();
return new LoanList(onSignOut: _signOut);
case Balancestatus.noBalance:
return CurrentBalancePage(
databaseRef: _databaseRef,
balanceSet: balanceSet,
);
default:
return new WelcomePage(onSignOut: _signOut);
}
}
}
class LoanList extends StatelessWidget {
final VoidCallback onSignOut;
LoanList({this.onSignOut});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: Text('Loans'),
actions: <Widget>[
new FlatButton(
child: new Text(
'Logout',
style: new TextStyle(fontSize: 17.0, color: Colors.white),
),
onPressed: onSignOut,
)
],
),
body: new Container(
padding: EdgeInsets.all(20.0),
alignment: Alignment.bottomCenter,
child: new RaisedButton(
child: new Text(
'New Loan',
style: new TextStyle(color: Colors.white, fontSize: 17.0),
),
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => NewLoan()));
},
color: Colors.blue,
),
),
);
}
void addNewLoan() {
print('Add new Loan');
}
}
class WelcomePage extends StatelessWidget {
final VoidCallback onSignOut;
WelcomePage({this.onSignOut});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text('Welcome'),
actions: <Widget>[
new FlatButton(
child: new Text(
'Logout',
style: new TextStyle(fontSize: 17.0, color: Colors.white),
),
onPressed: onSignOut,
)
],
),
body: new Container(
child: new Center(
child: new Text(
'Checking',
style: new TextStyle(fontSize: 32.0),
),
),
),
);
}
}

Related

I am creating note app in flutter and stuck in sqflite, how can I pass my title and body to insert method

I am building a simple note app, but I am stuck at saving the data (title and body) using SQLite.
DataBaseHelper class
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'model_notes.dart';
class DatabaseHelper {
static final _databaseName = "myNote.db";
static final _databaseVersion = 1;
static final table = 'notes_table';
static final columnId = 'id';
static final columnTitle = 'title';
static final columnBody = 'body';
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
static Database _database;
Future<Database> get database async {
if (_database != null) return _database;
_database = await _initDatabase();
return _database;
}
_initDatabase() async {
String path = join(await getDatabasesPath(), _databaseName);
return await openDatabase(path,
version: _databaseVersion,
onCreate: _onCreate);
}
Future _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE $table (
$columnId INTEGER PRIMARY KEY AUTOINCREMENT,
$columnTitle TEXT NOT NULL,
$columnBody TEXT NOT NULL
)
''');
}
Future<int> insert(Note note) async {
Database db = await instance.database;
return await db.insert(table, {'title': note.title, 'body': note.body});
}
This is the Model Class for Notes
import 'db_operations.dart';
class Note {
int id;
String title;
String body;
Note(this.id, this.title, this.body);
Note.fromMap(Map<String, dynamic> map) {
id = map['id'];
title = map['title'];
body = map['body'];
}
Map<String, dynamic> toMap(){
return {
DatabaseHelper.columnId : id,
DatabaseHelper.columnTitle : title,
DatabaseHelper.columnBody : body
};
}
}
and this is where I'm calling insert method (class name = adding_notes.dart)
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:note_taking_app/constants/buttons_and_icons_misc(classes).dart';
import 'package:note_taking_app/db/db_operations.dart';
import 'package:note_taking_app/db/model_notes.dart';
import 'package:sqflite/sqflite.dart';
import 'main_screen.dart';
final bodyController = TextEditingController();
final headerController = TextEditingController();
final dbHelper = DatabaseHelper.instance;
class AddingNotes extends StatefulWidget {
#override
_AddingNotesState createState() => _AddingNotesState();
}
class _AddingNotesState extends State<AddingNotes> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backwardsCompatibility: true,
leading: LeadingIcon(
callBack: () {
Navigator.pop(context);
},
),
backgroundColor: Colors.white.withOpacity(0.4),
actions: <Widget>[
ActionsIconButton(
icon: Icon(undo, color: black),
callBack: () {
debugPrint('undo tapped');
},
),
ActionsIconButton(
icon: Icon(redo, color: black),
callBack: () {
debugPrint('redo tapped');
},
),
ActionsIconButton(
icon: Icon(save, color: black),
callBack: () async {
debugPrint(bodyController.text);
debugPrint(headerController.text);
getHeaderDataToMainScreen(context);
String title = headerController.text;
String body = bodyController.text;
/*This is where I am calling insert method*/
dbHelper.insert(title, body);
},
)
],
),
body: Container(
color: Colors.white.withOpacity(0.4),
child: Padding(
padding: const EdgeInsets.all(13.0),
child: Column(
children: [
HeaderBody(
textEditingController: headerController,
),
SizedBox(
height: 32.0,
),
Expanded(
child: NotesBody(
textEditingController: bodyController,
),
),
],
),
),
),
);
}
}
getHeaderDataToMainScreen(BuildContext context){
Navigator.push(context,
MaterialPageRoute(
builder: (context) => MainScreen(
heading : headerController.text,
)
)
);
}
It is showing too many positional arguments expected 1 found 2. I know I need to send 1 argument, but how can I send both title and body as 1 argument. Maybe through List I can send it but I don't know how to do that. Any help here guys, I'm stuck at this for the past 5 days.
Check the example below that i have created based on the code you provided.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'db_operations.dart';
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: AddingNotes(),
));
}
final bodyController = TextEditingController();
final headerController = TextEditingController();
final dbHelper = DatabaseHelper.instance;
class AddingNotes extends StatefulWidget {
#override
_AddingNotesState createState() => _AddingNotesState();
}
class _AddingNotesState extends State<AddingNotes> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
leading: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
Icons.add,
color: Colors.black,
),
),
),
backgroundColor: Colors.white.withOpacity(0.4),
actions: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () {
debugPrint('undo tapped');
},
child: Icon(
Icons.undo,
color: Colors.black,
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () {
debugPrint('redo tapped');
},
child: Icon(
Icons.redo,
color: Colors.black,
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () async {
debugPrint(bodyController.text);
debugPrint(headerController.text);
//getHeaderDataToMainScreen(context);
String title = headerController.text;
String body = bodyController.text;
Note note = Note(20, title, body);
var value = await dbHelper.insert(note);
print("if 1 is return then insert success and 0 then not inserted : $value");
},
child: Icon(
Icons.save,
color: Colors.black,
),
),
)
],
),
body: Container(
color: Colors.white.withOpacity(0.4),
child: Padding(
padding: const EdgeInsets.all(13.0),
child: Column(
children: [
TextField(
controller: headerController,
),
SizedBox(
height: 32.0,
),
Expanded(
child: TextField(
controller: bodyController,
),
),
],
),
),
),
);
}
}
// getHeaderDataToMainScreen(BuildContext context) {
// Navigator.push(context,
// MaterialPageRoute(
// builder: (context) =>
// MainScreen(
// heading: headerController.text,
// )
// )
// );
// }
class Note {
int id;
String title;
String body;
Note(this.id, this.title, this.body);
Note.fromMap(Map<String, dynamic> map) {
id = map['id'];
title = map['title'];
body = map['body'];
}
Map<String, dynamic> toMap() {
return {
DatabaseHelper.columnId: id,
DatabaseHelper.columnTitle: title,
DatabaseHelper.columnBody: body
};
}
}
This is just a sample demo example added every thing in one file and made many changes. change it as per your needs.
You don't need a auto increment id as you have given it in the database. Run the app and let me know if it works.

Flutter the values in the array all become the same

Please understand that I am not good at English because I am a foreigner.
There was a problem while I was programming.
I was going to put each object in the array. We succeeded in putting the object in. But there was a problem with all the objects in the array being the same.
I want to solve this problem.
I'd appreciate it if you could help me.
Main.dart :
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'Page/FirstPage.dart';
import 'Page/FourPage.dart';
import 'Page/SecondPage.dart';
import 'Page/ThirdPage.dart';
import 'module/goal.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Index()),
ChangeNotifierProvider(create: (_) => Goal('None')),
ChangeNotifierProvider(create: (_) => GoalList())
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Todo App',
home: MainPage(),
),
);
}
}
class MainPage extends StatefulWidget {
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
var currentTab = [FirstPage(), SecondPage(), ThirdPage(), FourPage()];
#override
Widget build(BuildContext context) {
Index currentIndex = Provider.of<Index>(context);
Goal goal = Provider.of<Goal>(context);
return Scaffold(
body: IndexedStack(
index: currentIndex.currentIndex,
children: currentTab,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentIndex.currentIndex,
onTap: (index) {
currentIndex.currentIndex = index;
},
type: BottomNavigationBarType.fixed,
// 하단바 아이콘 고정
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.add_circle), title: Text('Todo Create')),
BottomNavigationBarItem(
icon: Icon(Icons.format_list_bulleted),
title: Text('Todo List')),
BottomNavigationBarItem(
icon: Icon(Icons.calendar_today), title: Text('none')),
BottomNavigationBarItem(
icon: Icon(Icons.settings), title: Text('none')),
],
selectedItemColor: Colors.black87,
// 선택된 index 색깔
unselectedItemColor: Colors.black54,
// 선택안된 index 색깔
),
);
}
}
Goal.dart
import 'package:flutter/cupertino.dart';
// 아이콘 설정 , 제목 , 기간 ,
class Goal with ChangeNotifier {
String _name;
String get getName => _name;
set setName(String name)=> _name = name;
Goal(this._name);
#override String toString() => _name;
}
class Index with ChangeNotifier {
int _currentIndex = 0;
get currentIndex => _currentIndex;
set currentIndex(int index) {
_currentIndex = index;
notifyListeners();
}
}
class GoalList with ChangeNotifier {
List<Goal> goalList = [];
Goal getGoal;
addGoalInList() {
goalList.add(getGoal);
notifyListeners();
}
}
FirstPage.dart
import 'package:flutter/material.dart';
import 'package:goalapp/module/goal.dart';
import 'package:provider/provider.dart';
class FirstPage extends StatefulWidget {
#override
_FirstPageState createState() => _FirstPageState();
}
// 객체를 만들 클래스를 생성
// 생성된 객체를 내부저장소에 저장
class _FirstPageState extends State<FirstPage> {
final _formKey = GlobalKey<FormState>();
TextEditingController _names = TextEditingController();
#override
void dispose() {
_names.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
Index currentIndex = Provider.of<Index>(context);
Goal goal = Provider.of<Goal>(context);
GoalList goalList = Provider.of<GoalList>(context);
return Scaffold(
appBar: AppBar(
title: Text('Todo add'),
),
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(
children: <Widget>[
Container(
width: 200,
height: 200,
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
controller: _names,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(10))),
filled: true,
hintText: 'Todo Name'),
),
],
),
),
),
RaisedButton(
onPressed: () {
goal.setName = _names.text;
goalList.getGoal = goal;
goalList.addGoalInList();
currentIndex.currentIndex = 1;
},
child: Text('Create'),
)
],
)
],
),
);
}
}
SecondPage.dart
import 'package:flutter/material.dart';
import 'package:goalapp/module/goal.dart';
import 'package:provider/provider.dart';
class SecondPage extends StatefulWidget {
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
#override
Widget build(BuildContext context) {
Goal goal = Provider.of<Goal>(context);
GoalList goalList = Provider.of<GoalList>(context);
return Scaffold(
appBar: AppBar(
title: Text('Todo ListView'),
),
body: Column(
children: <Widget>[
Expanded(
child: Consumer<GoalList>(builder: (context, goal, child) {
return ListView.separated(
itemCount: goal.goalList.length,
itemBuilder: (context, index) {
return Container(
child: ListTile(
title: Text(goalList.goalList[index].getName),
subtitle: Text('2020.07.16 ~ 2020.08.16'),
),
);
},
separatorBuilder: (context, index) {
return Divider();
},
);
}),
),
RaisedButton(
onPressed: () {
print(goalList.goalList[0]);
},
child: Text('List[0]'),
),
RaisedButton(
onPressed: () {
print(goalList.goalList[1]);
},
child: Text('List[1]'),
),
],
));
}
}
You can copy paste run full code below
Step 1: Change GoalList's addGoalInList(Goal goal)
class GoalList with ChangeNotifier {
List<Goal> goalList = [];
Goal getGoal;
addGoalInList(Goal goal) {
goalList.add(goal);
notifyListeners();
}
}
Step 2: You do not need Goal goal = Provider.of<Goal>(context);
#override
Widget build(BuildContext context) {
Index currentIndex = Provider.of<Index>(context);
// Goal goal = Provider.of<Goal>(context);
Step 3: Add goal with Goal goal = Goal(_names.text); then goalList.addGoalInList(goal);
RaisedButton(
onPressed: () {
Goal goal = Goal(_names.text);
//goal.setName = _names.text;
//goalList.getGoal = goal;
goalList.addGoalInList(goal);
currentIndex.currentIndex = 1;
},
child: Text('Create'),
)
working demo
full code
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter/cupertino.dart';
// 아이콘 설정 , 제목 , 기간 ,
class Goal with ChangeNotifier {
String _name;
String get getName => _name;
set setName(String name)=> _name = name;
Goal(this._name);
#override String toString() => _name;
}
class Index with ChangeNotifier {
int _currentIndex = 0;
get currentIndex => _currentIndex;
set currentIndex(int index) {
_currentIndex = index;
notifyListeners();
}
}
class GoalList with ChangeNotifier {
List<Goal> goalList = [];
Goal getGoal;
addGoalInList(Goal goal) {
goalList.add(goal);
notifyListeners();
}
}
class FirstPage extends StatefulWidget {
#override
_FirstPageState createState() => _FirstPageState();
}
// 객체를 만들 클래스를 생성
// 생성된 객체를 내부저장소에 저장
class _FirstPageState extends State<FirstPage> {
final _formKey = GlobalKey<FormState>();
TextEditingController _names = TextEditingController();
#override
void dispose() {
_names.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
Index currentIndex = Provider.of<Index>(context);
// Goal goal = Provider.of<Goal>(context);
GoalList goalList = Provider.of<GoalList>(context);
return Scaffold(
appBar: AppBar(
title: Text('Todo add'),
),
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(
children: <Widget>[
Container(
width: 200,
height: 200,
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
controller: _names,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(10))),
filled: true,
hintText: 'Todo Name'),
),
],
),
),
),
RaisedButton(
onPressed: () {
Goal goal = Goal(_names.text);
//goal.setName = _names.text;
//goalList.getGoal = goal;
goalList.addGoalInList(goal);
currentIndex.currentIndex = 1;
},
child: Text('Create'),
)
],
)
],
),
);
}
}
class SecondPage extends StatefulWidget {
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
#override
Widget build(BuildContext context) {
Goal goal = Provider.of<Goal>(context);
GoalList goalList = Provider.of<GoalList>(context);
return Scaffold(
appBar: AppBar(
title: Text('Todo ListView'),
),
body: Column(
children: <Widget>[
Expanded(
child: Consumer<GoalList>(builder: (context, goal, child) {
return ListView.separated(
itemCount: goal.goalList.length,
itemBuilder: (context, index) {
return Container(
child: ListTile(
title: Text(goalList.goalList[index].getName),
subtitle: Text('2020.07.16 ~ 2020.08.16'),
),
);
},
separatorBuilder: (context, index) {
return Divider();
},
);
}),
),
RaisedButton(
onPressed: () {
print(goalList.goalList[0]);
},
child: Text('List[0]'),
),
RaisedButton(
onPressed: () {
print(goalList.goalList[1]);
},
child: Text('List[1]'),
),
],
));
}
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Index()),
ChangeNotifierProvider(create: (_) => Goal('None')),
ChangeNotifierProvider(create: (_) => GoalList())
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Todo App',
home: MainPage(),
),
);
}
}
class MainPage extends StatefulWidget {
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
var currentTab = [FirstPage(), SecondPage()];
#override
Widget build(BuildContext context) {
Index currentIndex = Provider.of<Index>(context);
Goal goal = Provider.of<Goal>(context);
return Scaffold(
body: IndexedStack(
index: currentIndex.currentIndex,
children: currentTab,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentIndex.currentIndex,
onTap: (index) {
currentIndex.currentIndex = index;
},
type: BottomNavigationBarType.fixed,
// 하단바 아이콘 고정
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.add_circle), title: Text('Todo Create')),
BottomNavigationBarItem(
icon: Icon(Icons.format_list_bulleted),
title: Text('Todo List')),
BottomNavigationBarItem(
icon: Icon(Icons.calendar_today), title: Text('none')),
BottomNavigationBarItem(
icon: Icon(Icons.settings), title: Text('none')),
],
selectedItemColor: Colors.black87,
// 선택된 index 색깔
unselectedItemColor: Colors.black54,
// 선택안된 index 색깔
),
);
}
}

FLUTTER- I want to post and fetch datas from database

I am working on a flutter project and I want to fetch datas which I post to database. I can post successfully (I can see them in my database) but I cannot fetch data. I want your help... please help me... the codes, explanation and the problem below here.
the code:
class GetId {
String id;
GetId({this.id});
factory GetId.fromJson(Map<String, dynamic> json) {
return GetId(
id: json["id"],
);
}
}
Future<GetId> sendData() async {
_DenemeState controls = new _DenemeState();
final response = await http.post(
"https://www.ekrts.com.tr/bloom/get.php",
body: {
"id": "${controls.idController.text.toString()}"
},
);
if (response.statusCode == 200) {
return GetId.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load album');
}
}
class _DenemeState extends State<Deneme> {
TextEditingController nameController = TextEditingController();
TextEditingController surnameController = TextEditingController();
TextEditingController idController = TextEditingController();
Future<GetId> futureGetId;
Container _getValues() {
return Container(
child: Column(
children: <Widget>[
Text(
nameController.text.toString(),
),
Text(
'textfield değeri ' + idController.text.toString(),
),
Text(
"Response: ",
)
],
),
);
}
#override
void initState() {
super.initState();
futureGetId = sendData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Scaffold(
appBar: AppBar(
title: Text("Register"),
),
body: Container(
child: Center(
child: Column(
children: <Widget>[
Text(
"ad",
style: TextStyle(fontSize: 18.0),
),
TextField(
controller: nameController,
decoration: InputDecoration(hintText: 'ad'),
),
Text(
"soyad",
style: TextStyle(fontSize: 18.0),
),
TextField(
controller: surnameController,
decoration: InputDecoration(hintText: 'soyad'),
),
Text(
"id",
style: TextStyle(fontSize: 18.0),
),
TextField(
controller: idController,
decoration: InputDecoration(hintText: 'id'),
),
RaisedButton(
child: Text("Register"),
onPressed: () {
setState(() {
_getValues();
sendData();
});
},
),
_getValues(),
FutureBuilder<GetId>(
future: futureGetId,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data.id);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return CircularProgressIndicator();
},
),
],
),
),
),
),
);
}
}
Explanation:
GetId class: This class contains the data from network request
Future sendData(): This class connects my database and post the data to database, I can see them.
Container _getValues(): I created to see my data from the database on screen.
And my problem, I cannot see the data on emulator screen but I can post and see on database. I hope, I could explain my problem... please help me...
FirebaseAuth.instance.currentUser().then((user) {
id= user.uid;
});
i hope you are asking for something like this. you can load the user id to id variable from this.

Exception has occurred. ArgumentError (Invalid argument: Instance of 'Future<dynamic>') Flutter Dart

I want to save the User input from the TextFormField to Cloud_Firestore. The following error do i get below when i click the Save Button. VSCode points to the ".add".
DocumentReference ref = await db.collection('mealList').add({'Meal': meal, 'Date': _pickDate()});
At the Validator
Error running this Code
Exception has occurred. ArgumentError (Invalid argument: Instance of 'Future <.dynamic>')
Code
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:mealapp/models/global.dart';
import 'package:mealapp/models/Widgets/custom_date_time_picker.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
class WhatToEat extends StatefulWidget {
final FirebaseUser user;
WhatToEat({Key key, this.user }) : super(key: key);
#override
_WhatToEatState createState() => _WhatToEatState();
}
class _WhatToEatState extends State<WhatToEat> {
TextEditingController mealController = new TextEditingController();
String id;
final db = Firestore.instance;
final _formKey = GlobalKey<FormState>();
DateTime _selectedDate = DateTime.now();
String meal;
Color pickerColor = Color(0xff6633ff);
Color currentColor = Color(0xff6633ff);
Future _pickDate() async {
DateTime datepick = await showDatePicker(
context: context,
initialDate: new DateTime.now(),
firstDate: new DateTime.now().add(Duration(days: -365)),
lastDate: new DateTime.now().add(Duration(days: 365)));
if (datepick != null)
setState(() {
_selectedDate = datepick;
});
}
#override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Center(
child: Text(
"Add your new Meal",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
)),
SizedBox(
height: 24,
),
TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12))),
labelText: 'Enter your Meal'),
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
},
onSaved: (value) => meal = value,
),
CustomDateTimePicker(
icon: Icons.date_range,
onPressed: _pickDate,
value: new DateFormat("dd-MM-yyyy").format(_selectedDate),
),
_actionButton(),
],
),
),
);
}
Row _actionButton() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton(
onPressed: (){
Navigator.of(context).pop();
},
child: Text("Close"),
),
FlatButton(
onPressed: () async {
saveToFirestore();
Navigator.pop(context);
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12))
),
child: Text("Save"),
color: redColor,
textColor: Colors.white,
),
],
);
}
void saveToFirestore() async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
DocumentReference ref = await db.collection('mealList').add({'Meal': meal, 'Date': _pickDate()});
setState(() => id = ref.documentID);
print(ref.documentID);
}
}
}
How can i fix this Problem?
In the TextFormField at validator the Value String is underlined in blue.
Why is that so?
You are providing future value as a argument which is not valid.
try following.
void saveToFirestore() async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
await _pickDate();
DocumentReference ref = await db.collection('mealList').add({'Meal': meal, 'Date': _selectedDate});
setState(() => id = ref.documentID);
print(ref.documentID);
}
}

Rx.combineLatest2 not working as expected

I am a newbie in using flutter. I am try to create some sample application in flutter for create own application. I found a nice application in flutter with bloc pattern. please see the following link.
it's just a login page. there is a email and password textbox in the form with validation. One validator for email and another validator for the password length. There is a submit button in the form, initially it's disabled, if the email and password successfully validated then the submit button enabled. it uses the bloc pattern architecture with rxdart package.
I have a issue in submit button validation, after enter the email and password field it's not enabled the button field.
button validation code
Stream<bool> get submitCheck =>
Rx.combineLatest2(email, password, (e, p) => true);
Please see the below code.
main.dart
import 'package:bloc_login/pagetwo.dart';
import 'package:flutter/material.dart';
import 'package:bloc_login/bloc.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'Flutter Demo Home Page'),
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.teal,
),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
changethePage(BuildContext context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => PageTwo()));
}
#override
Widget build(BuildContext context) {
final bloc = Bloc();
return Scaffold(
appBar: AppBar(
title: Text("Bloc pattern"),
),
body: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
padding: EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
StreamBuilder<String>(
stream: bloc.email,
builder: (context, snapshot) => TextField(
onChanged: bloc.emailChanged,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: "Enter Email",
labelText: "Email",
errorText: snapshot.error),
),
),
SizedBox(
height: 20,
),
StreamBuilder<String>(
stream: bloc.password,
builder: (context, snapshot) => TextField(
onChanged: bloc.passwordChanged,
keyboardType: TextInputType.text,
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: "Enter password",
labelText: "Password",
errorText: snapshot.error),
),
),
SizedBox(
height: 20,
),
StreamBuilder<bool>(
stream: bloc.submitCheck,
builder: (context, snapshot) => RaisedButton(
color: Colors.tealAccent,
onPressed: (snapshot.data != null)
? () => changethePage(context)
: null,
child: Text("Submit"),
))
],
),
),
),
);
}
}
bloc.dart
import 'dart:async';
import 'package:bloc_login/validator.dart';
import 'package:rxdart/rxdart.dart';
class Bloc extends Object with Validators implements BaseBloc {
final _emailController = StreamController<String>();
final _passwordController = StreamController<String>();
Function(String) get emailChanged => _emailController.sink.add;
Function(String) get passwordChanged => _passwordController.sink.add;
Stream<String> get email => _emailController.stream.transform(emailValidator);
Stream<String> get password =>
_passwordController.stream.transform(passwordValidator);
Stream<bool> get submitCheck =>
Rx.combineLatest2(email, password, (e, p) => true);
#override
void dispose() {
_emailController.close();
_passwordController.close();
}
}
abstract class BaseBloc {
void dispose();
}
validator.dart
import 'dart:async';
mixin Validators {
var emailValidator =
StreamTransformer<String, String>.fromHandlers(handleData: (email, sink) {
if (email.contains("#")) {
sink.add(email);
} else {
sink.addError("Email is not valid.");
}
});
var passwordValidator = StreamTransformer<String, String>.fromHandlers(
handleData: (password, sink) {
if (password.length > 4) {
sink.add(password);
} else {
sink.addError("Password length should be greater than 4.");
}
});
}
Please advice.
Combinelatest2 are fine, the problem is that you are creating a new bloc in each rebuild.
So create the bloc in the initState method and dispose the bloc in the dispose method of the StatefulWidget.
But also your StreamControllers have a Stream that supports only one single subscriber, so if you want that theStream of the StreamControllercan be listened to more than once, this need to be a broadcast stream, one of the ways to do it is using the StreamController .broadcast () constructor.
P.D. If you are creating forms with the bloc pattern you can check flutter_form_bloc, it saves you a lot of code.
Since dart 2.1 you don't need to extend an object to use a mixin
class Bloc with Validators implements BaseBloc {
final _emailController = StreamController<String>.broadcast();
final _passwordController = StreamController<String>.broadcast();
//...
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Bloc _bloc;
#override
void initState() {
super.initState();
_bloc = Bloc();
}
#override
void dispose() {
_bloc.dispose();
super.dispose();
}
changethePage(BuildContext context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => PageTwo()));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Bloc pattern"),
),
body: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
padding: EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
StreamBuilder<String>(
stream: _bloc.email,
builder: (context, snapshot) => TextField(
onChanged: _bloc.emailChanged,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: "Enter Email",
labelText: "Email",
errorText: snapshot.error),
),
),
SizedBox(
height: 20,
),
StreamBuilder<String>(
stream: _bloc.password,
builder: (context, snapshot) => TextField(
onChanged: _bloc.passwordChanged,
keyboardType: TextInputType.text,
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: "Enter password",
labelText: "Password",
errorText: snapshot.error),
),
),
SizedBox(
height: 20,
),
StreamBuilder<bool>(
stream: _bloc.submitCheck,
builder: (context, snapshot) => RaisedButton(
color: Colors.tealAccent,
onPressed: (snapshot.data != null)
? () => changethePage(context)
: null,
child: Text("Submit"),
))
],
),
),
),
);
}
}

Resources