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 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.
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 색깔
),
);
}
}
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.
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);
}
}
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"),
))
],
),
),
),
);
}
}