getx obx not updating avatar image - Flutter GetX - flutter

what I want to achieve is to change the image in CircleAvatar when I'm selecting an image, here is the code:
ProfileController:
class ProfileController extends GetxController {
final TextEditingController emailController = TextEditingController();
final ImagePicker _picker = ImagePicker();
Rx<String?> avatarPath = null.obs;
avatarFromCamera() async {
var localAvatar = await _picker.pickImage(
source: ImageSource.camera, imageQuality: 50
);
if (localAvatar != null) {
avatarPath = localAvatar.path.obs;
update();
}
}
avatarFromGallery() async {
var localAvatar = await _picker.pickImage(
source: ImageSource.gallery, imageQuality: 50
);
if (localAvatar != null) {
avatarPath = localAvatar.path.obs;
update();
}
}
String? emailValidator(String? value) {
if (value == null || value.isEmpty) {
return null;
}
if (!EmailValidator.validate(value, false)) {
return 'Invalid email address';
}
}
#override
void onClose() {
emailController.dispose();
super.onClose();
}
String? emailValidator(String? value) {
if (value == null || value.isEmpty) {
return null;
}
if (!EmailValidator.validate(value, false)) {
return 'Invalid email address';
}
}
void save(GlobalKey<FormState> profileFormKey) {
if (profileFormKey.currentState!.validate()) {
print('valid');
}
}
}
and here is the ProfileScreen widget:
lass ProfileScreen extends StatelessWidget {
final ProfileController _profileController = Get.put<ProfileController>(ProfileController());
GlobalKey<FormState> profileFormKey = GlobalKey<FormState>();
ProfileScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Update user details'),
),
body: SingleChildScrollView(
child: Form(
key: profileFormKey,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(30.0),
child: TextFormField(
keyboardType: TextInputType.text,
controller: _profileController.emailController,
decoration: const InputDecoration(
labelText: 'Enter email',
),
validator: _profileController.emailValidator,
),
),
Center(
child: GestureDetector(
onTap: () {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return SafeArea(
child: Wrap(
children: <Widget>[
ListTile(
leading: const Icon(Icons.photo_library),
title: const Text('Photo Library'),
onTap: () {
_profileController.avatarFromGallery();
Navigator.of(context).pop();
}),
ListTile(
leading: const Icon(Icons.photo_camera),
title: const Text('Camera'),
onTap: () {
_profileController.avatarFromCamera();
Navigator.of(context).pop();
},
),
],
),
);
}
);
},
child: CircleAvatar(
radius: 55,
backgroundColor: Colors.pink,
child: Obx(() =>(_profileController.avatarPath.value != null)
? ClipRRect(
borderRadius: BorderRadius.circular(50),
child: Image.file(
File(_profileController.avatarPath.value!),
width: 100,
height: 100,
fit: BoxFit.fitHeight
),
)
: Container(
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(50)),
width: 100,
height: 100,
child: Icon(
Icons.camera_alt,
color: Colors.grey[800],
),
),
),
),
)),
Container(
margin: const EdgeInsets.all(10),
width: double.infinity,
child: MaterialButton(
color: Colors.blue,
onPressed: () => _profileController.save(profileFormKey),
child: const Text(
'Submit',
style: TextStyle(color: Colors.white),
),
),
),
],
),
),
),
);
}
}
as you can see, I have Obx and my avatarPath reactive, and I'm running update everywhere I changing it, but it's not udpated. I also tried to use empty string as initial value of imagePath like this Rx<String> avatarPath = ''.obs; and it's not working. What I'm doing wrong??? Thank you in advice!!!

There are two things to revise for it. Firstly, change avatarPath = localAvatar.path.obs; with avatarPath.value = localAvatar.path;. Because localAvatar.path.obs create the new observable and changes will not be reflected to previous observers.
Secondly, create a new stateless widget having the widget tree of bottom sheet's builder like
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return CustomBottomView();
}
);
Then inside the CustomBottomView copy your bottom sheet widget tree.
class CustomBottomView extends GetView<ProfileController> {
return YourBottomSheetWidgetTreeHere();
}
Dont worry about ProfileController here. You have already put it in DI in previous route. First follow the first step if you still face the problem second step will definitely resolve it.

Related

Error: NoSuchMethodError: 'then' Dynamic call of null. Receiver: null

Does anyone know the cause of this error? I have tried many ways but still don't know where the problem is.
Database.dart
import 'package:fitness_app/Login/login_data.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
class DatabaseService {
static final DatabaseService _databaseService = DatabaseService._internal();
factory DatabaseService() => _databaseService;
DatabaseService._internal();
static Database? _database;
Future<Database> get database async {
if (_database != null) return _database!;
_database = await _initDatabase();
return _database!;
}
Future<Database> _initDatabase() async {
final databasePath = await getDatabasesPath();
final path = join(databasePath, 'conference.database');
return await openDatabase(
path,
onCreate: _onCreate,
version: 1,
onConfigure: (db) async => await db.execute('PRAGMA foreign_keys = ON'),
);
}
Future<void> _onCreate(Database db, int version) async {
await db.execute(
'CREATE TABLE login(id INTEGER PRIMARY KEY, name TEXT, username TEXT, password TEXT)',
);
}
verifyuser(String user, String pass) {}
insertLoginData(Logindata logindata) {}
}
Login.dart
import 'package:fitness_app/Login/signup.dart';
import 'package:flutter/material.dart';
import 'login_data.dart';
import 'package:fitness_app/Database/database.dart';
import 'package:fitness_app/home_page.dart';
class Login extends StatefulWidget {
const Login({Key? key, this.login}) : super(key: key);
final Logindata? login;
#override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
String email = "a";
String pass = "a";
TextEditingController emails = TextEditingController();
TextEditingController password = TextEditingController();
final _formKey = GlobalKey<FormState>();
static final List<Logindata> _login = [];
final DatabaseService _databaseService = DatabaseService();
Future<List<Logindata>> _getLogin() async {
await _databaseService.verifyuser(email, pass).then((value) {
if (value) {
AlertDialog alert = AlertDialog(
title: const Text('Login successful!'),
content: const Text('Welcome!'),
actions: <Widget>[
TextButton(
onPressed: () => (Navigator.push(
context,
MaterialPageRoute(builder: (context) => const HomePage()),
)),
child: const Text('OK'),
),
],
);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
} else {
AlertDialog alert = AlertDialog(
title: const Text('Error!'),
content: const Text('Wrong Email or Password'),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context, 'OK'),
child: const Text('OK'),
),
],
);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
});
return _login;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SingleChildScrollView(
child: Column(
children: [
Container(
padding: EdgeInsets.all(10),
child: Form(
key: _formKey,
child: Column(
children: [
Text(
'BeFit:Fitness Activity Tracker Progress\n\n',
style: TextStyle(fontSize: 24),
textAlign: TextAlign.start,
),
Text(
'Welcome',
style: TextStyle(fontSize: 40),
textAlign: TextAlign.center,
),
SizedBox(
height: 30,
),
Container(
child: TextFormField(
controller: emails,
decoration: InputDecoration(
border: UnderlineInputBorder(
borderSide:
BorderSide(width: 1, color: Colors.grey)),
labelText: 'Email'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Email is required';
}
return null;
},
),
),
SizedBox(
height: 20,
),
Container(
child: TextFormField(
controller: password,
obscureText: true,
decoration: InputDecoration(
border: UnderlineInputBorder(
borderSide:
BorderSide(width: 1, color: Colors.grey)),
labelText: 'Password'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Password is required';
}
return null;
},
),
),
SizedBox(
height: 20,
),
Container(
width: MediaQuery.of(context).size.width,
height: 50,
child: FlatButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
email = emails.text;
pass = password.text;
_getLogin();
print(email);
print(pass);
print('success');
}
},
child: Text("Login"),
textColor: Colors.white,
color: Colors.deepPurple[400],
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(10)),
),
),
SizedBox(
height: 20,
),
Container(
child: Row(
children: <Widget>[
Text('Does not have account?'),
FlatButton(
textColor: Colors.deepPurpleAccent[100],
child: Text(
'Sign up',
style: TextStyle(fontSize: 16),
),
onPressed: () {
//signup screen
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SignUp()),
);
},
)
],
mainAxisAlignment: MainAxisAlignment.center,
))
],
),
),
)
],
),
),
),
);
}
}
Here is the error
enter image description here
I'm using this flutter to complete my project but there are some errors that I can't solve it. Sorry if my coding looks not right because still lacks in coding
Your verifyuser function does not return anything so your value returns null. You either need to return something or check for null values in your then statement.
Future<String> verifyuser(String user, String pass)async {
return user + pass;
}

Everything matches but I still get "Bad state: field does not exist within the DocumentSnapshotPlatform"

So i'm pretty lost trying to get my app to fetch not only the desired text from firestore but also the image i placed there. I know the error "Bad state: field does not exist within the DocumentSnapshotPlatform" implies that either I'm missing field or there's something wrong with at least one of those fields. There's only four things I'm trying to fetch from firestore "imgUrl, title, desc, organizer" i have checked for spelling and order and i can't figure it out. I have also checked firestore to see if the order and spelling was correct and i dont see what's the issue. Please help, Thank you so much in advanced.
////////////////////////////// News Class Starts\\\\\\\\\\\\\\
import 'package:myfuji/screens/CrudMethods.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'CrudMethods.dart';
import 'add_blog.dart';
class News extends StatefulWidget {
#override
_NewsState createState() => _NewsState();
}
class _NewsState extends State<News> {
CrudMethods crudMethods = CrudMethods();
late QuerySnapshot blogSnapshot;
#override
void initState() {
crudMethods.getData().then((result) {
blogSnapshot = result;
setState(() {});
});
super.initState();
}
Widget blogsList() {
return ListView.builder(
padding: const EdgeInsets.only(top: 24),
itemCount: blogSnapshot.docs.length,
itemBuilder: (context, index) {
return BlogTile(
organizer: blogSnapshot.docs[index].get('Organizer'),
desc: blogSnapshot.docs[index].get('desc'),
imgUrl: blogSnapshot.docs[index].get('imgUrl'),
title: blogSnapshot.docs[index].get('title'),
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Events"),
),
body: Container(
child: blogSnapshot != null
? blogsList()
: const Center(
child: CircularProgressIndicator(),
)),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => AddBlog()));
},
),
);
}
}
class BlogTile extends StatelessWidget {
final String imgUrl, title, desc, organizer;
const BlogTile(
{required this.organizer,
required this.desc,
required this.imgUrl,
required this.title});
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(bottom: 24, right: 16, left: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: Image.network(
imgUrl,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
height: 200,
),
),
),
const SizedBox(height: 16),
Text(
title,
style: const TextStyle(fontSize: 17),
),
const SizedBox(height: 2),
Text(
'$desc - By $organizer',
style: const TextStyle(fontSize: 14),
)
],
),
);
}
}
///////////////////////////////////////////// class AddBlog begins here \\\\\\\\\\\
import 'dart:io';
import 'package:myfuji/screens/CrudMethods.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:random_string/random_string.dart';
class AddBlog extends StatefulWidget {
#override
_AddBlogState createState() => _AddBlogState();
}
class _AddBlogState extends State<AddBlog> {
//
late File selectedImage;
final picker = ImagePicker();
bool isLoading = false;
CrudMethods crudMethods = new CrudMethods();
Future getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
if (pickedFile != null) {
selectedImage = File(pickedFile.path);
} else {
print('No image selected.');
}
});
}
Future<void> uploadBlog() async {
if (selectedImage != null) {
// upload the image
setState(() {
isLoading = true;
});
Reference firebaseStorageRef = FirebaseStorage.instance
.ref()
.child("events/")
.child("${randomAlphaNumeric(9)}.jpg");
final UploadTask task = firebaseStorageRef.putFile(selectedImage);
var imageUrl;
await task.whenComplete(() async {
try {
imageUrl = await firebaseStorageRef.getDownloadURL();
} catch (onError) {
print("Error");
}
print(imageUrl);
});
// print(downloadUrl);
Map<String, dynamic> blogData = {
"imgUrl": imageUrl,
"Organizer": authorTextEditingController.text,
"title": titleTextEditingController.text,
"desc": descTextEditingController.text
};
crudMethods.addData(blogData).then((value) {
setState(() {
isLoading = false;
});
Navigator.pop(context);
});
// upload the blog info
}
}
//
TextEditingController titleTextEditingController =
new TextEditingController();
TextEditingController descTextEditingController = new TextEditingController();
TextEditingController authorTextEditingController =
new TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Create Blog"),
actions: [
GestureDetector(
onTap: () {
uploadBlog();
},
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Icon(Icons.file_upload)),
)
],
),
body: isLoading
? Container(
child: Center(
child: CircularProgressIndicator(),
))
: SingleChildScrollView(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 16),
child: Column(
children: [
GestureDetector(
onTap: () {
getImage();
},
child: selectedImage != null
? Container(
height: 150,
margin: EdgeInsets.symmetric(vertical: 24),
width: MediaQuery.of(context).size.width,
child: ClipRRect(
borderRadius:
BorderRadius.all(Radius.circular(8)),
child: Image.file(
selectedImage,
fit: BoxFit.cover,
),
),
)
: Container(
height: 150,
decoration: BoxDecoration(
color: Colors.grey,
borderRadius:
BorderRadius.all(Radius.circular(8))),
margin: EdgeInsets.symmetric(vertical: 24),
width: MediaQuery.of(context).size.width,
child: Icon(
Icons.camera_alt,
color: Colors.white,
),
),
),
TextField(
controller: titleTextEditingController,
decoration: InputDecoration(hintText: "enter title"),
),
TextField(
controller: descTextEditingController,
decoration: InputDecoration(hintText: "enter desc"),
),
TextField(
controller: authorTextEditingController,
decoration:
InputDecoration(hintText: "enter author name"),
),
],
)),
),
);
}
}
///////////////////////////////////////////// class CrudMethods begins here \\\\\\\\\\\
import 'package:cloud_firestore/cloud_firestore.dart';
class CrudMethods {
Future<void> addData(blogData) async {
print(blogData);
FirebaseFirestore.instance
.collection("events/")
.add(blogData)
.then((value) => print(value))
.catchError((e) {
print(e);
});
}
getData() async {
return await FirebaseFirestore.instance.collection("events/").get();
}
}
/////////////////////////////////////////////firestore\\\\\\\\\\\\\
This maybe related to having “/“ after collection name here:
.collection("events/")
Instead try this:
.collection("events")
Also it may be best to change child to collection here:
Reference firebaseStorageRef = FirebaseStorage.instance
.ref()
.child("events/")
Try to see if you get data back by running this:
itemCount: blogSnapshot.docs.length,
itemBuilder: (context, index) {
QuerySnapshot snap = blogSnapshot.data; // Snapshot
List<DocumentSnapshot> items = snap.documents; // List of Documents
DocumentSnapshot item = items[index]; Specific Document
return BlogTile(
organizer: item.data['Organizer'],
desc: item.data['desc'],
imgUrl: item.data['imgUrl'],
title: item.data['title'],
);
},
I think you need to utilize a QueryDocumentSnapshot to access the data in the document.

I dont want to display all the records of table in listview but I want to display records of only particular customer in flutter

I have a screen which shows list of customers using listview. Next when I click on a customer I want to show the notes(records) only of that particular customer(customerId) in next screen in listview. I know how to display all the records of table. but how to display only certain records?? Neither there is any error nor the listview is being displayed. I dont know where am I going wrong.
List<CustomerNote> cnoteList;
int count = 0;
if (cnoteList == null) {
cnoteList = List<CustomerNote>();
updateCustomerNotes();
}
db_service.dart
Future<List<CustomerNote>> getCustomerNotes(int customer) async {
await DB.init();
var res = await DB.rawQuery("noteDetails WHERE custId = '$customer'");
int count = res.length;
List<CustomerNote> cnotelist = List<CustomerNote>();
for (int i = 0; i < count; i++) {
cnotelist.add(CustomerNote.fromMap(res[i]));
}
return cnotelist;
}
People_List.dart //this is the file which displays list of customers
import 'package:customer/models/Note.dart';
import 'package:customer/models/addCustomer.dart';
import 'package:customer/screens/New_Note.dart';
import 'package:customer/screens/Note_info.dart';
import 'package:customer/screens/User_Settings.dart';
import 'package:customer/screens/add_person.dart';
import 'package:customer/services/db_service.dart';
import 'package:customer/utils/database_helper.dart';
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:sqflite/sqflite.dart';
class People_List extends StatefulWidget{
#override
State<StatefulWidget> createState() {
return People_ListState();
}
}
class People_ListState extends State<People_List> with SingleTickerProviderStateMixin{
DBService dbService = DBService();
List<AddCustomer> customerList;
int count = 0;
static final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();
var _isSelectedItemIndex;
TextEditingController _searchQuery;
bool _isSearching = false;
String searchQuery = "Search query";
#override
void initState() {
super.initState();
_searchQuery = new TextEditingController();
}
void _startSearch() {
print("open search box");
ModalRoute
.of(context)
.addLocalHistoryEntry(new LocalHistoryEntry(onRemove: _stopSearching));
setState(() {
_isSearching = true;
});
}
void _stopSearching() {
_clearSearchQuery();
setState(() {
_isSearching = false;
});
}
void _clearSearchQuery() {
print("close search box");
setState(() {
_searchQuery.clear();
updateSearchQuery("Search query");
});
}
Widget _buildTitle(BuildContext context) {
var horizontalTitleAlignment =
Platform.isIOS ? CrossAxisAlignment.center : CrossAxisAlignment.start;
return new InkWell(
onTap: () => scaffoldKey.currentState.openDrawer(),
child: new Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: horizontalTitleAlignment,
children: <Widget>[
const Text(''),
],
),
),
);
}
Widget _buildSearchField() {
return new TextField(
controller: _searchQuery,
autofocus: true,
decoration: const InputDecoration(
hintText: 'Search...',
border: InputBorder.none,
hintStyle: const TextStyle(color: Colors.white30),
),
style: const TextStyle(color: Colors.white, fontSize: 16.0),
onChanged: updateSearchQuery,
);
}
void updateSearchQuery(String newQuery) {
setState(() {
searchQuery = newQuery;
});
print("search query " + newQuery);
}
List<Widget> _buildActions() {
if (_isSearching) {
return <Widget>[
new IconButton(
icon: const Icon(Icons.clear),
onPressed: () {
if (_searchQuery == null || _searchQuery.text.isEmpty) {
Navigator.pop(context);
return;
}
_clearSearchQuery();
},
),
];
}
return <Widget>[
new IconButton(
icon: const Icon(Icons.search),
onPressed: _startSearch,
),
];
}
#override
Widget build(BuildContext context) {
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
if (customerList == null) {
customerList = List<AddCustomer>();
updateListView();
}
return Scaffold(
appBar: new AppBar(
leading: _isSearching ? const BackButton() : null,
title: _isSearching ? _buildSearchField() : _buildTitle(context),
actions: _buildActions(),
),
body:getCustomerListView(),
floatingActionButton: FloatingActionButton(
onPressed: () {
navigateToCustomer(AddCustomer(), 'Add Person');
},
child: const Icon(Icons.add),
),
bottomNavigationBar:Row (
children: <Widget>[
buildNavBarItem(Icons.home,0,"Home"),
buildNavBarItem(Icons.fiber_new_rounded,1,"Upcoming"),
buildNavBarItem(Icons.history,2,"History"),
buildNavBarItem(Icons.account_circle,3,"Account"),
],
),
);
}
ListView getCustomerListView() {
TextStyle titleStyle = Theme.of(context).textTheme.subhead;
return ListView.builder(
itemCount: count,
itemBuilder: (BuildContext context, int position) {
return Card(
color: Colors.white,
elevation: 2.0,
child: ListTile(
/*trailing: CircleAvatar(
backgroundColor: getPriorityColor(this.noteList[position].priority),
child: getPriorityIcon(this.noteList[position].priority),
),*/
title: Text(this.customerList[position].custName, style: titleStyle,),
//subtitle: Text(this.customerList[position].date),
onTap: () {
},
),
);
},
);
}
void navigateToCustomer(AddCustomer customer, String title) async {
bool result = await Navigator.push(context, MaterialPageRoute(builder: (context) {
return AddPerson(customer, title);
}));
if (result == true) {
updateListView();
}
}
void updateListView() {
final Future<Database> dbFuture = DB.init();
dbFuture.then((database) {
Future<List<AddCustomer>> customerListFuture = dbService.getCustomerList();
customerListFuture.then((customerList) {
setState(() {
this.customerList = customerList;
this.count = customerList.length;
});
});
});
}
Widget buildNavBarItem(IconData icon,int index,title) {
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
return GestureDetector(
onTap: () {
setState(() {
_isSelectedItemIndex=index;
if(_isSelectedItemIndex==3) {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => User_Settings()));
}
});
},
child: Container(
height: height * 0.09,
width: width / 4,
decoration: index==_isSelectedItemIndex?BoxDecoration(
border: Border(
bottom: BorderSide(width: 4,color: Theme.of(context).primaryColor),
),
gradient: LinearGradient(colors: [
Theme.of(context).primaryColor.withOpacity(0.3),
Theme.of(context).primaryColor.withOpacity(0.015),
],begin: Alignment.bottomCenter,end: Alignment.topCenter)
):BoxDecoration(),
child: Column(
children: <Widget>[
InkWell(
child: Icon(icon,
color: index==_isSelectedItemIndex? Theme.of(context).primaryColor:Colors.black54,
),
),
Text(title)
],)),
);
}
}
Note_Info.dart
class Note_Info extends StatefulWidget{
final String appBarTitle;
final AddCustomer customer;
Note_Info(this. customer, this.appBarTitle);
#override
State<StatefulWidget> createState() {
return Note_InfoState(this.customer,this.appBarTitle);
}
}
class Note_InfoState extends State<Note_Info> {
CustomerNote note=CustomerNote();
DBService dbService = DBService();
List<CustomerNote> cnoteList;
int count = 0;
String appBarTitle;
AddCustomer customer;
Note_InfoState(this.customer, this.appBarTitle);
PickedFile _imageFile;
final ImagePicker _picker = ImagePicker();
bool rememberMe = false;
DateTime _date = DateTime.now();
TextEditingController custNameController = TextEditingController();
void getImage(ImageSource source) async {
final pickedFile = await _picker.getImage(
source: source);
setState(() {
_imageFile = pickedFile;
});
}
#override
Widget build(BuildContext context) {
if (noteList == null) {
noteList = List<CustomerNote>();
updateCustomerNotes();
}
var height = MediaQuery.of(context).size.height;
custNameController.text = customer.custName;
return DefaultTabController(
length: 4,
child: Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(
Icons.add,
),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => NewNote()));
},
)
],
),
body: Container(
child: Column(
children: <Widget>[
TextField(controller: custNameController,
style: TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
textAlign: TextAlign.center),
Padding(
padding: const EdgeInsets.all(15.0),
child: Row(children: [
ImageProfile(),
Padding(
padding: const EdgeInsets.only(left: 30.0),
child: IconButton(
icon: Icon(
Icons.call,
color: Colors.green,
size: 45,
),
onPressed: () {
},
),
),
],),
),
SizedBox(
height: 50,
child: AppBar(
bottom: TabBar(
tabs: [
Tab(
text: "All",
),
Tab(
text: "Pending",
),
Tab(
text: "Cancelled",
),
Tab(
text: "Completed",
),
],
),
),
),
// create widgets for each tab bar here
Expanded(
child: TabBarView(
children: [
// first tab bar view widget
Container(
child: getNoteListView(),
),
// second tab bar view widget
Container(
child: Center(
child: Text(
'Pending Items',
),
),
),
Container(
child: Center(
child: Text(
'Cancelled',
),
),
),
Container(
child: Center(
child: Text(
'Completed',
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 55.0,
width: 200,
child: RaisedButton(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
color: Theme
.of(context)
.primaryColorDark,
textColor: Colors.white,
child: Text('Save', textScaleFactor: 1.5,),
onPressed: () {
setState(() {
//_reset();
});
},
),
),
),
]
),
)
));
}
void updateCustomerNotes() {
final Future<Database> dbFuture = DB.init();
dbFuture.then((database) {
int customerId=customer.custId;
Future<List<CustomerNote>> noteListFuture = dbService.getCustomerNotes(customerId);
noteListFuture.then((cnoteList) {
setState(() {
this.cnoteList = cnoteList;
//this.count = cnoteList.length;
});
});
});
}
ListView getNoteListView() {
TextStyle titleStyle = Theme.of(context).textTheme.subhead;
return ListView.builder(
itemCount: count,
itemBuilder: (BuildContext context, int position) {
return Card(
color: Colors.white,
elevation: 2.0,
child: ListTile(
title: Text(this.cnoteList[position].note, style: titleStyle,),
subtitle: Text(this.cnoteList[position].date),
trailing: GestureDetector(
child: Icon(Icons.delete, color: Colors.grey,),
onTap: () {
},
),
onTap: () {
},
),
);
},
);
}
void _showSnackBar(BuildContext context, String message) {
final snackBar = SnackBar(content: Text(message));
Scaffold.of(context).showSnackBar(snackBar);
}
Widget ImageProfile() {
return Center(
child: CircleAvatar(
radius: 80.0,
backgroundImage: AssetImage('images/person_icon.jpg')
),
);
}
}
If u want to get some specific data from the server then you need to provide (where: ) in your query such as
List<Map> result = await db.query(
DatabaseHelper.table,
columns: columnsToSelect,
where: whereString,
whereArgs: whereArguments);
// print the results
result.forEach((row) => print(row));
// {_id: 1, name: Bob, age: 23}
}
Note your query can be different from the above one.
and if you want to get the same specific data from already fetched data then also you need to use the where clause such as
final outData = responseData.where((i) => i.userId == customerId).toList();
and then pass the outData to next page through params.

Display selected data from database using AlertDialog in flutter

Hi im trying to display the specific or selected data from database using alert dialog however the data i want to display doesn't display to alertDialog by the way im using floor for my database im pretty stack on this any suggestion or idea will be well appreciated.
Here is my code
Widget buildAboutDialog(BuildContext context,
AddContactCallback _contactscreen, bool isEdit, ContactObject _contactObject) {
final databases = $FloorContactDatabase.databaseBuilder('Contacts.cb').build();
if(contactObject != null) {
this.contactObject = _contactObject;
tfirstname.text = _contactObject.firstname;
tlastname.text = _contactObject.lastname;
tbirthday.text = _contactObject.birthday;
tcontactnumber = _contactObject.contactnumber as TextEditingController ;
tprofilepicture = _contactObject.profilepicture as File;
} else {
print('ERROR');
print(tfirstname.value);
}
return new AlertDialog(
title: new Text(isEdit ? 'Contact!' : 'Contact'),
content: new SingleChildScrollView(
child: new Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 10.0,
),
Align(
alignment: Alignment.center,
child: CircleAvatar(
radius: 70,
backgroundColor: Color(0xff476cfb),
child: ClipOval(
child: new SizedBox(
width: 180.0,
height: 180.0,
child: (_image != null) ? Image.file(_image, // Image.file(File('${_contactsDao.profilepicture}'),
fit: BoxFit.fill,
) : Image.network(
"https://images.unsplash.com/photo-1502164980785-f8aa41d53611?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
fit: BoxFit.fill,
),
),
),
),
),
getTextFieled("First Name", tfirstname),
getTextFieled("Last Name", tlastname),
getTextFieled("Birth day", tbirthday),
getTextFieled("Contact No", tcontactnumber),
],
),
),
);
}
And here is the functions and instance
Widget getTextFieled(
String inputData, TextEditingController inputTextController) {
var btm = new Padding(
padding: const EdgeInsets.all(5.0),
child: new TextFormField(
controller: inputTextController,
decoration: new InputDecoration(
hintText: inputData,
),
),
);
return btm;
}
Widget getAppButton (String buttonLabel, EdgeInsets margin){
var btm = new Container(
margin: margin,
padding: EdgeInsets.all(8.0),
alignment: FractionalOffset.center,
decoration: new BoxDecoration(
border: Border.all(color: const Color(0xFF28324E)),
borderRadius: new BorderRadius.all(const Radius.circular(6.0)),
),
child: new Text(
buttonLabel,
style: new TextStyle(
color: const Color(0xFF28324E),
fontSize: 20.0,
fontWeight: FontWeight.w300,
letterSpacing: 0.3,
),
),
);
return btm;
}
ContactObject getdata(bool isEdit) {
return new ContactObject(
firstname: tfirstname.text,
lastname: tfirstname.text,
birthday: tbirthday.text,
contactnumber: int.parse(tcontactnumber.text),
profilepicture: tprofilepicture.readAsStringSync(),
);
}
onTap(bool isEdit, AddContactCallback addContactCallback, BuildContext context) {
if(isEdit) {
addContactCallback.updateContacts(getdata(isEdit));
Navigator.of(context).pop();
print('ANG PUMASOK');
print(tfirstname);
} else {
Fluttertoast.showToast(
msg: 'ERROR ERROR',
toastLength: Toast.LENGTH_SHORT,
timeInSecForIosWeb: 1,
gravity: ToastGravity.BOTTOM
);
}
}
}
abstract class AddContactCallback {
void updateContacts(ContactObject contactObject);
}
here is the Screenshot of my idea
This method has been used for a long time to modify an item in a list or other.
This code is just an example of how it works.
in base widget write this:
class BaseWidget extends StatefulWidget {
#override
_BaseWidgetState createState() => new _BaseWidgetState();
}
class _BaseWidgetState extends State<BaseWidget> {
#override
void initState() {
// get data from data base
_getDataFromDataBase();
super.initState();
}
var _listComingDataFromDataBase;
#override
Widget build(BuildContext context) {
return Scaffold(
body: _listComingDataFromDataBase == null
? Container(
width: 50,
height: 50,
child: CircularProgressIndicator(),
)
: RefreshIndicator(
onRefresh: () async {
_getDataFromDataBase();
},
child: ListView.builder(
itemBuilder: (context, index) {
return InkWell(
child: Container(
height: 100,
),
onTap: () {
_buildAlertDialog(
context,
_listComingDataFromDataBase[
index]); //open dialog and send selected object
},
);
},
itemCount: _listComingDataFromDataBase.length,
),
),
);
}
void _buildAlertDialog(context, selectedObject) {
showDialog(
context: context,
child: AlertDialog(
content: EditObjectWidget(selectedObject),
)).then((isEdited) {
if (isEdited) {
// you can reload data from database
_getDataFromDataBase();
}
});
}
void _getDataFromDataBase() {
// database.getData.then((data){setState(){_listComingDataFromDataBase = data};});
}
}
Create EditObjectWidget Like this:
class EditObjectWidget extends StatefulWidget {
final selectedObject;
EditObjectWidget(this.selectedObject);
#override
_EditObjectWidgetState createState() => _EditObjectWidgetState();
}
class _EditObjectWidgetState extends State<EditObjectWidget> {
final TextEditingController _firstNameController = TextEditingController();
final TextEditingController _numberController = TextEditingController();
#override
void initState() {
fillFields(widget.selectedObject);
super.initState();
}
void fillFields(selectedObject) {
_firstNameController.text = selectedObject.fistName ?? '';
if (selectedObject.number != null)
_numberController.text = selectedObject.number.toString();
}
#override
void dispose() {
_firstNameController.dispose();
_numberController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
TextField(
controller: _firstNameController,
),
TextField(
controller: _numberController,
keyboardType: TextInputType.number,
),
RaisedButton(
onPressed: () {
_updateObject();
},
child: Text('Submit'),
)
],
);
}
void _updateObject() {
//update object in data base
// database.updateObject({'number':_numberController.text,'first_name':_firstNameController.text});
//if updateObject method return true, close dialog with true result, Otherwise false
bool isEdited = true;
if(!isEdited)
{
//show validation error, or another
}
else
Navigator.pop(context, isEdited);
}
}
I did not use your code, it is only an explanation
Hope this code helps you
I think the value needs to be set to TextFormField after setting the TextEditingController for it.
Try before returning the widget, set a value;
Widget getTextFieled(
String inputData, TextEditingController inputTextController) {
var btm = new Padding(
padding: const EdgeInsets.all(5.0),
child: new TextFormField(
controller: inputTextController,
decoration: new InputDecoration(
hintText: inputData,
),
),
);
inputTextController.text = "Some Value Test";
return btm;
}

how to use useStreamController in HookWidget?

Im new to flutter hooks, and riverpod(state-manangement),
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _url = "https://owlbot.info/api/v4/dictionary/";
String _token = "ae7cbdfff57e548a4360348ee519123a741d8e3d";
TextEditingController _controller = TextEditingController();
StreamController _streamController;
Stream _stream;
Timer _debounce;
Future _search() async {
if (_controller.text == null || _controller.text.length == 0) {
_streamController.add(null);
return;
}
_streamController.add("waiting");
Response response = await get(_url + _controller.text.trim(),
headers: {"Authorization": "Token " + _token});
_streamController.add(json.decode(response.body));
}
#override
void initState() {
super.initState();
_streamController = StreamController();
_stream = _streamController.stream;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flictionary"),
bottom: PreferredSize(
preferredSize: Size.fromHeight(48.0),
child: Row(
children: <Widget>[
Expanded(
child: Container(
margin: const EdgeInsets.only(left: 12.0, bottom: 8.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(24.0),
),
child: TextFormField(
onChanged: (String text) {
if (_debounce?.isActive ?? false) _debounce.cancel();
_debounce = Timer(const Duration(milliseconds: 1000), () {
_search();
});
},
controller: _controller,
decoration: InputDecoration(
hintText: "Search for a word",
contentPadding: const EdgeInsets.only(left: 24.0),
border: InputBorder.none,
),
),
),
),
IconButton(
icon: Icon(
Icons.search,
color: Colors.white,
),
onPressed: () {
_search();
},
)
],
),
),
),
body: Container(
margin: const EdgeInsets.all(8.0),
child: StreamBuilder(
stream: _stream,
builder: (BuildContext ctx, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Center(
child: Text("Enter a search word"),
);
}
if (snapshot.data == "waiting") {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
itemCount: snapshot.data["definitions"].length,
itemBuilder: (BuildContext context, int index) {
return ListBody(
children: <Widget>[
Container(
color: Colors.grey[300],
child: ListTile(
leading: snapshot.data["definitions"][index]
["image_url"] ==
null
? null
: CircleAvatar(
backgroundImage: NetworkImage(snapshot
.data["definitions"][index]["image_url"]),
),
title: Text(_controller.text.trim() +
"(" +
snapshot.data["definitions"][index]["type"] +
")"),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
snapshot.data["definitions"][index]["definition"]),
)
],
);
},
);
},
),
),
);
}
}
i just wanted to convert above statefulWidget to HookWidget and how to use riverpod as statemanagenent for the above example. I know some basics of hooks and riverpod, but still i'm confused between the hooks, statemanagement(riverpod).
Please Can someone help understand them and provide some examples or at least convert the above code into the hook widget, and using hookbuilder
Thanks in advance
First off, the code:
final textProvider = StateProvider<String>((_) => '');
final responseFutureProvider =
FutureProvider.autoDispose.family<Response, String>((ref, text) async {
if (text == null || text.length == 0) {
throw Error();
}
final String _url = "https://owlbot.info/api/v4/dictionary/";
final String _token = "ae7cbdfff57e548a4360348ee519123a741d8e3d";
return await get(_url + text.trim(), headers: {"Authorization": "Token " + _token});
});
final responseProvider = Computed<AsyncValue<Response>>((read) {
final text = read(textProvider).state;
return read(responseFutureProvider(text));
});
String _useDebouncedSearch(TextEditingController controller) {
final search = useState(controller.text);
useEffect(() {
Timer? timer;
void listener() {
timer?.cancel();
timer = Timer(
const Duration(milliseconds: 1000),
() => search.value = controller.text,
);
}
controller.addListener(listener);
return () {
timer?.cancel();
controller.removeListener(listener);
};
}, [controller]);
return search.value;
}
class MyHomePage extends HookWidget {
const MyHomePage({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
final controller = useTextEditingController();
final text = useProvider(textProvider);
text.state = _useDebouncedSearch(controller);
return Scaffold(
appBar: AppBar(
title: Text("Flictionary"),
bottom: PreferredSize(
preferredSize: Size.fromHeight(48.0),
child: Row(
children: <Widget>[
Expanded(
child: Container(
margin: const EdgeInsets.only(left: 12.0, bottom: 8.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(24.0),
),
child: TextFormField(
controller: controller,
decoration: InputDecoration(
hintText: "Search for a word",
contentPadding: const EdgeInsets.only(left: 24.0),
border: InputBorder.none,
),
),
),
),
Icon(
Icons.search,
color: Colors.white,
),
],
),
),
),
body: MyHomePageBody(),
);
}
}
class MyHomePageBody extends HookWidget {
const MyHomePageBody({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
final text = useProvider(textProvider).state;
final response = useProvider(responseProvider);
response.when(
error: (err, stack) => Center(child: Text('Error: $err')),
loading: () => Center(child: CircularProgressIndicator()),
data: (response) => ListView.builder(
itemCount: Response["definitions"].length,
itemBuilder: (BuildContext context, int index) {
return ListBody(
children: <Widget>[
Container(
color: Colors.grey[300],
child: ListTile(
leading: response["definitions"][index]["image_url"] == null
? null
: CircleAvatar(
backgroundImage:
NetworkImage(response["definitions"][index]["image_url"]),
),
title: Text(text.trim() + "(" + response["definitions"][index]["type"] + ")"),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(response["definitions"][index]["definition"]),
)
],
);
},
),
);
}
}
We add an external text provider so that we can read the text field from other providers.
We create a FutureProviderFamily so that we can perform the API call with a parameter, the text from your text field. In Riverpod, families enable the passing parameters to providers.
We create a Computed that will call the Future every time the value of the text provider changes. This returns an AsyncValue which is a wonderful replacement to the StreamBuilder you were using (will explain more).
Refactored your debounced search a bit to use the useEffect hook. This will handle disposing the resources for your timer and update the textProvider as necessary. (I learned this from Remi's Marvel example)
We no longer need an onChanged or manual button press to search, as the textprovider's state is being updated whenever the controller changes.
Moved the body of your page into its own class to separate what needs to be loaded from what is static.
Now, instead of a StreamBuilder, we can use AsyncValue to handle the loading, error, and success states of your build.
I know this was a lot to cover, so I'd recommend really digging into the docs to learn more about everything that's in this example.