I have 2 pages in a flutter project. The first one is loginPage, which it's used for get user profile through Amplify DataStore query right after the login successful:
void _login() async{
final username = _usernameController.text.trim();
final password = _passwordController.text.trim();
ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Entrando no sistema...aguarde'), backgroundColor: Colors.green ) );
print('username: $username');
print('password: $password');
try{
_amplify.Auth.signOut();
var authResponse = await _amplify.Auth.signIn(username: username, password: password);
if (authResponse.isSignedIn){
List<Paciente> _listPacientes = await _amplify.DataStore.query(Paciente.classType, where: Paciente.EMAIL.eq(_usernameController.text.trim()));
Navigator.push(context, MaterialPageRoute(builder: (_) => MyHomePage(_listPacientes.elementAt(0))));
}
}
on AuthException catch (e){
print(e);
ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(e.message), backgroundColor: Colors.red ) );
}
}
And the HomePage whih I'd to show the results of the query executed in previous page (Login):
import 'package:flutter/material.dart';
import 'package:hmv/models/ModelProvider.dart';
import 'package:hmv/views/profile.dart';
class MyHomePage extends StatefulWidget {
Paciente paciente = new Paciente();
MyHomePage({Key? key, required Paciente paciente})
: super(key: key);
#override
State<StatefulWidget> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Paciente paciente = new Paciente();
void initState() async{
super.initState();
paciente = widget.paciente;
}
int _selectedIndex = 0;
List<Widget> _pages = <Widget>[
Text(
'Nome do paciente: ${paciente.nome_completo}'
),
Icon(
Icons.phone,
size: 150,
),
Icon(
Icons.camera,
size: 150,
),
Icon(
Icons.chat,
size: 150,
),
];
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
body: SafeArea(
child: Center(
child: _pages.elementAt(_selectedIndex)
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedIndex, //New
onTap: _onItemTapped,
fixedColor: const Color(0xFF0065B3),
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: "Home",
),
BottomNavigationBarItem(
icon: Icon(Icons.medical_services),
label: "Saúde",
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: "Perfil",
),
],
),
);
}
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
}
But when I try to use the page's parameters, I got the folowing error:
The instance member 'paciente' can't be accessed in an initializer.
Try replacing the reference to the instance member with a different expression
class MyHomePage extends StatefulWidget {
Paciente paciente = new Paciente();
MyHomePage({Key? key, required Paciente paciente})
: super(key: key);
replace it with
class MyHomePage extends StatefulWidget {
Paciente paciente;
MyHomePage({Key? key, required this.paciente})
: super(key: key);
also change your State:
class _MyHomePageState extends State<MyHomePage> {
// Remove these lines
// Paciente paciente = new Paciente();
// void initState() async{
// super.initState();
// paciente = widget.paciente;
// }
int _selectedIndex = 0;
List<Widget> _pages = <Widget>[
Text(
'Nome do paciente: ${widget.paciente.nome_completo}'
),
Related
I'm trying to save and read a list called "teams" as a shared_preference so every time I switch back to this screen and take a look at my teams list it isn't empty and shows the old values. No matter how I set it up it doesn't seem to work. Then I come back the list is empty. Do you guys have any ideas?
Here is my code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class TeamScreen extends StatefulWidget {
#override
_TeamScreenState createState() => _TeamScreenState();
}
class _TeamScreenState extends State<TeamScreen> {
List<String> teams = [];
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: teams.length,
itemBuilder: (context, index) {
return Team(
teams[index],
() => removeTeam(teams[index]),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () => newTeam(),
child: Icon(
CupertinoIcons.add,
),
),
);
}
void addTeam(String name) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
teams.add(name);
});
Navigator.of(context).pop();
prefs.setStringList('teams', teams);
}
void newTeam() {
showDialog<AlertDialog>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Name auswählen: '),
content: TextField(
onSubmitted: addTeam,
),
);
},
);
}
void removeTeam(String name) {
setState(() {
teams.remove(name);
});
}
}
class Team extends StatelessWidget {
final String name;
final Function remove;
const Team(this.name, this.remove);
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 22),
child: ListTile(
leading: Icon(Icons.sports_volleyball_outlined),
contentPadding: EdgeInsets.symmetric(vertical: 8.0),
title: Text(
name,
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w600,
),
),
trailing: IconButton(
icon: Icon(CupertinoIcons.delete),
onPressed: () => remove(),
),
),
);
}
}
Your code seems almost perfect! just you didn't initialized your teams variable with the SharedPreferences in initState.
lets fix that :
Define a prefs variable
class _TeamScreenState extends State<TeamScreen> {
List<String> teams = [];
late SharedPreferences prefs; //Declare your prefs variable here but with late initializer.
...
Check if teams list is stored in local -> fetch it or if not -> create it with empty list.
void initState() {
super.initState();
tryListFetch(); // defined async function
}
void tryListFetch() async {
prefs = await SharedPreferences.getInstance();
if (!prefs.containsKey('teams')) {
prefs.setStringList('teams', []); // created empty teams list on local storage
print('On device data is not available.');
return;
}
print('data avaialble');
teams = prefs.getStringList('teams') as List<String>;
}
Update your local data whenever you make changes in teams variable :
prefs.setStringList('teams', teams);
like in your removeTeam function :
void removeTeam(String name) {
setState(() {
teams.remove(name);
});
prefs.setStringList('teams', teams); //updated local storage's list
}
And in your addTeam function :
void addTeam(String name) async {
// SharedPreferences prefs = await SharedPreferences.getInstance(); //no need to initialize it here as we have already initialized it globally!
setState(() {
teams.add(name);
});
Navigator.of(context).pop();
prefs.setStringList('teams', teams);
}
Done !
I have a registration form in my application and I want to check if the DropDown value is empty or not. So I will give a warning to the screen. But I couldn't use DropDown value on checkFieldStatus function. How can I get this?
These are my codes that i used for my app:
class Register extends StatefulWidget {
#override
_RegisterState createState() => _RegisterState();
}
class _RegisterState extends State<Register> {
List listGender = ["Erkek", "Kız"];
List listTeacher = ["Oğulcan Baybars", "Kübra Yeşilkazak"];
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
String genderHolder;
String teacherHolder;
var _imageFile = null;
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
children: [
CustomDropDownField(
list: listGender,
hintText: "Cinsiyet",
value: genderHolder,
),
CustomDropDownField(
list: listTeacher,
hintText: "Öğretmeniniz",
value: teacherHolder,
),
ElevatedButton(
onPressed: () {
checkFieldStatus();
},
child: Text("Kayıt Ol")),
],
),
),
);
}
Future<void> checkFieldStatus() async {
if (_imageFile != null) {
showDialog(
context: context,
builder: (context) {
return ErrorAlertDialog(
message: "Resim yüklendi",
);
});
} else {
**Where I want to do the checks**
? registerUser()
: displayDialog("Lütfen formdaki bütün alanları doldurun.";
}
}
}
My CustomDropDownField like this:
import 'package:flutter/material.dart';
class CustomDropDownField extends StatefulWidget {
final List list;
final String hintText;
String value;
CustomDropDownField({
Key key,
this.list,
this.hintText,
this.value,
}) : super(key: key);
#override
_CustomDropDownFieldState createState() => _CustomDropDownFieldState();
}
class _CustomDropDownFieldState extends State<CustomDropDownField> {
#override
Widget build(BuildContext context) {
return Container(
child: DropdownButton(
isExpanded: true,
hint: Text(widget.hintText),
items: widget.list.map((valueItem) {
return DropdownMenuItem(value: valueItem, child: Text(valueItem));
}).toList(),
value: widget.value,
onChanged: (newValue) {
setState(() {
widget.value = newValue;
});}),);}
CustomDropDownField only changes the String value in its own state it does not reflect to the _RegisterState screen you can do a few different things:
Pass a callback function that updates the value in the _RegisterState screen
or even better
Use a state management like Provider or Bloc to update the value.
I want to create a list, those people location = "Barishal". That's why, I created a function and try to push data ( which data I obtained from getSpecific() function ) to a new list ( myList ). But It created a problem ....
here is my code-
class BookData extends ChangeNotifier {
List<MyModel> data = [
MyModel(name: "Abir", location: "Dhaka"),
MyModel(name: "Shuvro", location: "Barishal"),
MyModel(name: "Anik", location: "Barishal")
];
List<MyModel> get getMydata{
return data;
}
getSpecific (){
for(int i=0;i<data.length;i++){
if(data[i].location=="Barishal"){
print(data[i]);
return data[i];
}
}
}
List myList = getSpecific();
}
How can I fix this problem ?
You can copy paste run full code below
You can provide search string and use UnmodifiableListView<MyModel> and filter with _myData.where
code snippet
class BookData extends ChangeNotifier {
final List<MyModel> _myData = [
MyModel(name: "Abir", location: "Dhaka"),
MyModel(name: "Shuvro", location: "Barishal"),
MyModel(name: "Anik", location: "Barishal")
];
String _searchString = "";
UnmodifiableListView<MyModel> get books => _searchString.isEmpty
? UnmodifiableListView(_myData)
: UnmodifiableListView(
_myData.where((dog) => dog.location.contains(_searchString)));
void getSpecific(String searchString) {
_searchString = searchString;
print(_searchString);
notifyListeners();
}
}
working demo
full code
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'dart:collection';
import 'package:provider/provider.dart';
class BookData extends ChangeNotifier {
final List<MyModel> _myData = [
MyModel(name: "Abir", location: "Dhaka"),
MyModel(name: "Shuvro", location: "Barishal"),
MyModel(name: "Anik", location: "Barishal")
];
String _searchString = "";
UnmodifiableListView<MyModel> get books => _searchString.isEmpty
? UnmodifiableListView(_myData)
: UnmodifiableListView(
_myData.where((dog) => dog.location.contains(_searchString)));
void getSpecific(String searchString) {
_searchString = searchString;
print(_searchString);
notifyListeners();
}
}
class MyModel {
final String name;
final String location;
MyModel({this.name, this.location});
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => BookData(),
child: MyApp(),
),
);
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _controller = TextEditingController();
String _searchText;
#override
void initState() {
_controller.addListener(
() {
setState(() {
_searchText = _controller.text;
});
},
);
super.initState();
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Example',
home: Scaffold(
appBar: AppBar(
title: Text('Example'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
TextField(
controller: _controller,
decoration: InputDecoration(
hintText: "Search",
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(4.0),
),
),
),
onChanged: (value) {
Provider.of<BookData>(context, listen: false)
.getSpecific(value);
},
),
Consumer<BookData>(builder: (context, bookData, child) {
print(bookData.books.toString());
return Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: bookData.books.length,
itemBuilder: (context, index) => Card(
elevation: 3,
child: ListTile(
title: Text(bookData.books[index].name),
),
)),
);
}),
],
),
),
);
}
}
When you need to filter a list, you can use the where method.
Here's a simple example.
List<MyModel> myNewList = data.where((item) => item.location == "Barishal").toList();
Anyway, your code seems to be returning just the first item, not a list.
I fixed your code like below
List<MyModel> getSpecific (){
List<MyModel> result = [];
for(int i=0;i<data.length;i++){
if(data[i].location=="Barishal"){
print(data[i]);
result.add(data[i]);
}
}
return result;
}
Here is my point: I have two pages. The first page has a textFormField and it's value I send to the second screen. In the second screen I want to create a list of what I received from the first page. But the problem is that the list is never created. It just shows the last element received.
import 'package:flutter/material.dart';
class PageTwo extends StatefulWidget {
final String descricao;
const PageTwo({Key key, this.descricao}) : super(key: key);
#override
_PageTwoState createState() => _PageTwoState();
}
class _PageTwoState extends State<PageTwo> {
final List<String> listDescricao = [];
#override
void initState() {
listDescricao.add(widget.descricao);
super.initState();
}
//List images items
Widget imgListItem() {
return ListView.builder(
itemCount: listDescricao.length,
itemBuilder: (BuildContext context, int index) {
return widget.descricao == null
? Container()
: Text(listDescricao[index]);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: imgListItem(),
);
}
}
As required this is the PAGE ONE:
import 'package:flutter/material.dart';
class PageOne extends StatefulWidget {
#override
_PageOneState createState() => _PageOneState();
}
class _PageOneState extends State<PageOne> {
final GlobalKey<ScaffoldState> _scaffoldkey = new GlobalKey<ScaffoldState>();
final inputDescricaoController = TextEditingController();
//send image
doSend() async {
String descricao = inputDescricaoController.text ??= "";
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (BuildContext context) => PageTwo(descricao: descricao)),
(Route<dynamic> route) => false);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: RaisedButton(
child: Column(
children: <Widget>[
TextField(
controller: inputDescricaoController,
),
Text(
'send',
),
],
),
onPressed: () async {
doSend();
},
),
);
}
}
In the 'Categories' class I have a list of elements. This list will be completed with more categories from Firebase. I want to read this list in another view (showCategories.dart) and thus output it in the other (showCategories.dart) view.
How can I pass the list to another view and access the elements of the list in this other view?
Code for categories.dart
class Categories with ChangeNotifier {
List<Category> _cats = [
Category(
id: 'c1',
titel: 'Kategorie #1',
bezeichnung: 'Erste Kategorie',
gruppe: '1',
),
Category(
id: 'c2',
titel: 'Kategorie #2',
bezeichnung: 'Zweite Kategorie',
gruppe: '2',
),
Category(
id: 'c3',
titel: 'Kategorie #3',
bezeichnung: 'Dritte Kategorie',
gruppe: '3',
),
];
List<Category> get cats {
return [..._cats];
}
get length => null;
Category findById(String id) {
return _cats.firstWhere(
(prod) => prod.id == id
);
}
Future<void> fetchAndSetCategories() async {
const url = 'https://....firebaseio.com/categories.json';
//print(_cats);
try {
final response = await http.get(url);
final extractedData = json.decode(response.body) as Map<String, dynamic>;
final List<Category> loadedCategories = [];
extractedData.forEach((catId, catData) {
loadedCategories.add(Category(
id: catId,
titel: catData['titel'],
bezeichnung: catData['bezeichnung'],
gruppe: catData['gruppe'],
));
});
_cats = loadedCategories;
notifyListeners();
} catch(error) {
throw error;
}
}
}
Code for viewCategories.dart
class ViewCategories extends StatefulWidget {
#override
_ViewCategoriesState createState() => _ViewCategoriesState();
}
class _ViewCategoriesState extends State<ViewCategories> {
#override
void initState() {
Provider.of<Categories>(context, listen: false).fetchAndSetCategories();
super.initState();
}
}
You can copy paste run full code below
You can directly use Consumer to access data of your model
code snippet
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => Categories(),
child: MyApp(),
),
);
}
...
return Scaffold(
body: Consumer<Categories>(builder: (context, categoryData, child) {
print(categoryData.cats.toString());
return ListView.builder(
shrinkWrap: true,
itemCount: categoryData.cats.length,
itemBuilder: (context, index) => Card(
elevation: 3,
child: ListTile(
title: Text(categoryData.cats[index].titel),
),
));
}),
);
working demo
full code
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:provider/provider.dart';
import 'dart:convert';
class ViewCategories extends StatefulWidget {
#override
_ViewCategoriesState createState() => _ViewCategoriesState();
}
class _ViewCategoriesState extends State<ViewCategories> {
#override
void initState() {
//Provider.of<Categories>(context, listen: false).fetchAndSetCategories();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Consumer<Categories>(builder: (context, categoryData, child) {
print(categoryData.cats.toString());
return ListView.builder(
shrinkWrap: true,
itemCount: categoryData.cats.length,
itemBuilder: (context, index) => Card(
elevation: 3,
child: ListTile(
title: Text(categoryData.cats[index].titel),
),
));
}),
);
}
}
class Category {
String id;
String titel;
String bezeichnung;
String gruppe;
Category({this.id, this.titel, this.bezeichnung, this.gruppe});
}
class Categories with ChangeNotifier {
List<Category> _cats = [
Category(
id: 'c1',
titel: 'Kategorie #1',
bezeichnung: 'Erste Kategorie',
gruppe: '1',
),
Category(
id: 'c2',
titel: 'Kategorie #2',
bezeichnung: 'Zweite Kategorie',
gruppe: '2',
),
Category(
id: 'c3',
titel: 'Kategorie #3',
bezeichnung: 'Dritte Kategorie',
gruppe: '3',
),
];
List<Category> get cats {
return [..._cats];
}
get length => null;
Category findById(String id) {
return _cats.firstWhere((prod) => prod.id == id);
}
Future<void> fetchAndSetCategories() async {
const url = 'https://....firebaseio.com/categories.json';
//print(_cats);
try {
/*final response = await http.get(url);
final extractedData = json.decode(response.body) as Map<String, dynamic>;
final List<Category> loadedCategories = [];
extractedData.forEach((catId, catData) {
loadedCategories.add(Category(
id: catId,
titel: catData['titel'],
bezeichnung: catData['bezeichnung'],
gruppe: catData['gruppe'],
));
});*/
final List<Category> loadedCategories = [];
loadedCategories.add(Category(
id: "c9",
titel: 'c9 titel',
bezeichnung: 'c9 bezeichnung',
gruppe: 'c9 gruppe',
));
loadedCategories.add(Category(
id: "c19",
titel: 'c19 titel',
bezeichnung: 'c19 bezeichnung',
gruppe: 'c19 gruppe',
));
_cats = loadedCategories;
notifyListeners();
} catch (error) {
throw error;
}
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => Categories(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Demo'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Consumer<Categories>(builder: (context, categoryData, child) {
print(categoryData.cats.toString());
return Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: categoryData.cats.length,
itemBuilder: (context, index) => Card(
elevation: 3,
child: ListTile(
title: Text(categoryData.cats[index].titel),
),
)),
);
}),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Provider.of<Categories>(context, listen: false).fetchAndSetCategories();
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ViewCategories()),
);
},
child: Icon(Icons.navigation),
backgroundColor: Colors.green,
));
}
}