mapEventToState not trigerring using BLOC pattern, Flutter - flutter

I'm using flutter to develop an application and decides to use the bloc pattern as recommended by google, however the event I defined is never getting triggered. I defined the event to be when a check for connectivity happens a boolean is returned from the controller to the view.
Below is the relevant code
login controller.dart
import 'package:XXXXX/connection.dart';
import 'package:bloc/bloc.dart';
import 'package:connectivity/connectivity.dart';
class LoginBloc extends Bloc<Connectivity,bool> {
#override
bool get initialState => false;
#override
Stream<bool> mapEventToState(Connectivity event) async*{
// TODO: implement mapEventToState
switch(await event.checkConnectivity()){
case ConnectivityResult.mobile:
yield true;
break;
case ConnectivityResult.wifi:
yield true;
break;
case ConnectivityResult.none:
yield false;
}
}
}
class LoginWidget extends StatefulWidget {
#override
LoginWidgetState createState() {
return LoginWidgetState();
}
}
class LoginWidgetState extends State<LoginWidget> {
#override
Widget build(BuildContext context) {
//final _loginBloc = BlocProvider.of<LoginBloc>(context);
const oneSec = const Duration(seconds: 1);
//_loginBloc.add(ConnectivityResult.checkConnectivity());
new Timer.periodic(oneSec, (Timer t) => Connectivity().checkConnectivity());
return Scaffold(
body: BlocProvider(
builder: (BuildContext context) => LoginBloc(),
child: new Form(
key: _formKey,
child: ListView(
padding: EdgeInsets.only(top: 50.0),
children: <Widget>[
Image.asset(
'assets/images/XXXXX_logo.jpg',
height: 70,
width: 100,
alignment: Alignment.center,
),
_buildTextFields(),
_buildButtons(),
],
),
),
));
}
Widget _buildTextFields() {
return new Container(
padding: EdgeInsets.only(left: 16.0, right: 16.0),
child: new Column(
children: <Widget>[
new Container(
child: new TextFormField(
controller: _userFilter,
decoration: new InputDecoration(labelText: 'Username'),
validator: (value) {
if (value.isEmpty) {
return 'Username cannot be empty';
}
return null;
},
),
),
new Container(
child: new TextFormField(
controller: _passwordFilter,
decoration: new InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (value) {
if (value.isEmpty) {
return 'Password cannot be empty';
}
return null;
}),
)
],
),
);
}
Widget _buildButtons() {
return new Container(
child: new Column(
children: <Widget>[
new RaisedButton(
child: new Text('Login'),
onPressed: () {
if (_formKey.currentState.validate()) {
_loginPressed();
}
}),
new BlocBuilder<LoginBloc, bool>(
builder: (BuildContext context, bool state) {
return Container(
color: state ? Colors.greenAccent : Colors.redAccent,
padding: EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
state ? "Connected" : "No Internet Connection",
textAlign: TextAlign.center,
)
],
),
);
}),
],
),
);
}

As stated in the name of the function mapEventToState what actually does is in the response of an event added to the Bloc sink will be called and then you will be able to yield a state out, this will be received by the BlocBuilder in your UI when this happens, so in order to make this work as you expected you should probably create an Event, then instantiate your Bloc using for instance BlocProvider and dispatch an event from there.
So based on your code
final _loginBloc = BlocProvider.of<LoginBloc>(context);
_loginBloc.add(YourEvent());
Then in the mapEventToState
Stream<bool> mapEventToState(LoginEvent event) async*{
if (event is YourEvent) {
yield YourState();
}

Related

How to access methods in one class an call it in another classes method in flutter (dart)

I have a method called handleSignIn. I want to call it inside a class that handles sign in when the screen orientantion is mobile. How can I access the method from one class to another class?
this is my first class
class _SignInState extends State<SignIn> {
#override
void initState() {
super.initState();
MsalMobile.create('assets/auth_config.json', authority).then((client) {
setState(() {
msal = client;
});
refreshSignedInStatus();
});
}
/// Signs a user in
void handleSignIn() async {
await msal.signIn(null, [SCOPE]).then((result) {
// ignore: unnecessary_statements
refreshSignedInStatus();
}).catchError((exception) {
if (exception is MsalMobileException) {
logMsalMobileError(exception);
} else {
final ex = exception as Exception;
print('exception occurred');
print(ex.toString());
}
});
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Scaffold(
backgroundColor: Color(0xff392850),
body: Responsive(
mobile: _HomeScreenMobile(
),
// desktop: _HomeScreenDesktop(),
),
),
);
}
}
my _HomeScreenMobile class
class _HomeScreenMobile extends StatelessWidget{
bool isSignedIn = false;
Widget build(BuildContext context) {
ProgressDialog progressDialog = ProgressDialog(context, type:ProgressDialogType.Normal, isDismissible: false, );
progressDialog.style(message: "Signing you in ...");
return Scaffold(
body: Builder(
builder: (context) => Stack(
fit: StackFit.expand,
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Image.asset('assets/landing.webp',
fit: BoxFit.fill,
color: Color.fromRGBO(255, 255, 255, 0.6),
colorBlendMode: BlendMode.modulate),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: 10.0),
Container(
width: 130.0,
child: Align(
alignment: Alignment.center,
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0)),
color: Color(0xffffffff),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(
FontAwesomeIcons.microsoft,
color: Color(0xFF01A6F0),
),
// Visibility(
// visible: !isSignedIn,
SizedBox(width: 10.0),
Visibility(
visible: !isSignedIn,
child: Text(
'Sign in',
style: TextStyle(
color: Colors.black, fontSize: 18.0),
),
),
],
),
onPressed: () => {
progressDialog.show(),
handleSignIn(),
})),
)
],
),
],
),
),
);
}
}
how can I access handleSign from _HomeScreenMobile without it throwing the error The method 'handleSignIn' isn't defined for the type '_HomeScreenMobile'.. Have tried going through the example shared no luck
HomeScreenMobile could get its reference as a parameter and call it whenever it's necessary.
class _HomeScreenMobile extends StatelessWidget{
bool isSignedIn = false;
_HomeScreenMobile({this.handleSignInReference});
final Future<void> Function() handleSignInReference;
...
onPressed: () => {
progressDialog.show(),
handleSignInReference(),
}
}
Finally, where you call this class:
Responsive(
mobile: _HomeScreenMobile(
handleSignInReference:handleSignIn
),
)
You could create a handle_signin.dart file:
void handleSignIn() async {
await msal.signIn(null, [SCOPE]).then((result) {
refreshSignedInStatus();
}).catchError((exception) {
if (exception is MsalMobileException) {
logMsalMobileError(exception);
} else {
final ex = exception as Exception;
print('exception occurred');
print(ex.toString());
}
});
}
Import it wherever you need it:
import './handle_signin.dart`;
And use it:
#override
Widget build() {
return Scaffold(body: Center(GestureDetector(onTap: () async { await handleSignIn(); })));
}
Important note: while the code above might work for your case, it's highly recommended that you consider more sophisticated approaches to state management and Widget communication, such as BLoC.

Flutter - Returning to previous page from AppBar is not refreshing the page, with Navigator.pop(context)

I was trying to get the list page refreshed if a method was run on another page. I do pass the context using the push navigation.
I tried to follow these 3 answers Answer 1 Answer 2 and Answer 3 and I am not able to manage the states here.
This is the first list page which needs to be refreshed. It calls a class
class _PageLocalState extends State<PageLocal> {
#override
Widget build(BuildContext context) {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: SafeArea(
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: widget.allLocal.length,
//padding: const EdgeInsets.only(top: 10.0),
itemBuilder: (context, index) {
return LocalCard(widget.allLocal[index]);
},
)),
)
],
),
);
}
}
The next class:
class LocalCardState extends State<LocalCard> {
FavData localdet;
LocalCardState(this.localdet);
ListTile makeListTile() => ListTile(
contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
title: Text(
localdet.name,
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(localdet.loc),
trailing: Icon(Icons.keyboard_arrow_right, size: 30.0),
onTap: () => navigateToDetail(localdet),
);
Widget get localCard {
return new Card(
elevation: 4.0,
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: Container(
child: makeListTile(),
));
}
#override
Widget build(BuildContext context) {
return new Container(
child: localCard,
);
}
navigateToDetail(FavData localdet) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FavouriteDetailPage(
mndet: localdet,
)));
setState(() {});
}
}
Now this is routing to the final detail page:
class _FavouriteDetailPageState extends State<FavouriteDetailPage> {
bool isFav = false;
FavData mndet;
_FavouriteDetailPageState(this.mndet);
// reference to our single class that manages the database
final dbHelper = DatabaseHelper.instance;
#override
Widget build(BuildContext context) {
Widget heading = new Container(...);
Widget middleSection = new Expanded(...);
Widget bottomBanner = new Container(...);
Widget body = new Column(...);
final makeBottom = Container(
height: 55.0,
child: BottomAppBar(
color: Color.fromRGBO(36, 36, 36, 1.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new FavIconWidget(mndet),
],
),
),
);
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('The Details'),
backgroundColor: Color.fromRGBO(36, 36, 36, 1.0),
),
body: Container(
child: Card(
elevation: 5.0,
shape: RoundedRectangleBorder(
side: BorderSide(color: Colors.white70, width: 1),
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.all(20.0),
child: Padding(
padding: new EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: body,
),
),
),
bottomNavigationBar: makeBottom,
);
}
void share(BuildContext context, FavData mndet) {
final RenderBox box = context.findRenderObject();
final String shareText = "${mndet.name} - ${mndet.desc}";
Share.share(shareText,
subject: mndet.loc,
sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size);
}
}
class FavIconWidget extends StatefulWidget {
final FavData mnforIcon;
FavIconWidget(this.mnforIcon);
#override
_FavIconWidgetState createState() => _FavIconWidgetState();
}
class _FavIconWidgetState extends State<FavIconWidget> {
final dbHelper = DatabaseHelper.instance;
Future<bool> get isFav async {
final rowsPresent = await dbHelper.queryForFav(widget.mnforIcon.id);
if (rowsPresent > 0) {
print('Card Loaded - Its Favourite already');
return false;
} else {
print('Card Loaded - It is not favourite yet');
return true;
}
}
void _insert() async {...}
void _delete() async {...}
#override
Widget build(BuildContext context) {
return FutureBuilder<bool>(
future: isFav,
initialData:
false, // you can define an initial value while the db returns the real value
builder: (context, snapshot) {
if (snapshot.hasError)
return const Icon(Icons.error,
color: Colors.red); //just in case the db return an error
if (snapshot.hasData)
return IconButton(
icon: snapshot.data
? const Icon(Icons.favorite_border, color: Colors.white)
: Icon(Icons.favorite, color: Colors.red),
onPressed: () => setState(() {
if (!snapshot.data) {
print('Its favourite so deleting it.');
_delete();
} else {
print('Wasnt fav in the first place so inserting.');
_insert();
}
}));
return CircularProgressIndicator(); //if there is no initial value and the future is not yet complete
});
}
}
I am sure this is just some silly coding I have done but just not able to find out. Where.
I tried adding Navigator.pop(context); in different sections of the detail page and it fails.
Currently, I have to navigate back to the Favourites list page and then HomePage and then back to Favourites ListPage to refresh the list.
try this.. Anywhere you are using Navigator.pop or Navigator.push .. Instead of this use this:
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (BuildContext context) => Password())
);
//instead of Password use the name of the page(the second page you want to go to)

Flutter reload Ui after refreshing FutureBuilder

in this my code, when application couldn't get data from web server, that can be show reload button, after that when i click on reload button, my method can be get data from web server again, my problem is after this action i can't reload UI with this data and reload button is shown always
class _LessonDetailState extends BaseState<LessonDetail> {
String monthKey;
String lessonFileKey;
int monthId;
_LessonDetailState(this.monthKey, this.lessonFileKey,this.monthId);
Future<PlayLessonResponse> _myResponse;
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey = new GlobalKey<RefreshIndicatorState>();
#override
void initState() {
Future.delayed(Duration.zero,() {
_myResponse = _getLessonDetail(context, monthKey, lessonFileKey);
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.rtl,
child: Scaffold(
body: FutureBuilder<PlayLessonResponse>(
future: _myResponse,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if(snapshot.hasData){
//...
}else{
return RefreshIndicator(
key: _refreshIndicatorKey,
child: Container(
width: double.infinity,
height: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
padding: EdgeInsets.all(15),
child: Text(
'Error',
style: AppTheme.of(context).caption(),
),
),
RaisedButton(
color: Colors.white,
child: Text(
'Reload',
style: AppTheme.of(context).caption(),
),
onPressed: (){
return _getLessonDetail(context, monthKey, lessonFileKey);
},
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0))),
],
),
),
onRefresh: (){
return _getLessonDetail(context, monthKey, lessonFileKey);
},
);
}
}
return Center(
child: CircularProgressIndicator(),
);
}),
),
);
}
Future<PlayLessonResponse> _getLessonDetail(BuildContext context, String monthKey, String lessonFileKey) async {
try{
//...
return PlayLessonResponse.fromJson(response.body);
}catch(error){
print(error);
return null;
}
}
}
In your onRefresh's _getLessonDetail() function, you should call setState() to rebuild the widget
setState(() {
_myResponse = _getLessonDetail(context, monthKey, lessonFileKey);
});

Deleting widget from list from a press within the widget

I have a list of custom TextFormField's that i added to them a delete icon
all I am trying to do is when I press the delete button it will be deleted from the list and the view
i tried adding a function to my form field with no success
I think my approach isn't the best way to implement what i want, I am open to any idea
here is the code
import 'package:flutter/material.dart';
typedef DeleteCallback = void Function(Key key);
class DynamicFormField extends FormField<String>{
DynamicFormField({
Key key,
FormFieldSetter<String> onSaved,
FormFieldValidator<String> validator,
String initialValue = "",
bool autovalidate = false,
DeleteCallback onDelete(Key key),
}) : super(
onSaved: onSaved,
validator: validator,
initialValue: initialValue,
autovalidate: autovalidate,
builder: (FormFieldState<String> state) {
return Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
flex: 5,
child: TextFormField(
decoration: const InputDecoration(
hintText: 'Enter Player Name',
),
onSaved: onSaved,
validator: validator,
initialValue: initialValue,
autovalidate: autovalidate,
),
),
IconButton(
icon: Icon(Icons.delete_outline),
onPressed: onDelete(key)
),
],
);
}
);
}
DynamicFormField(
key: UniqueKey(),
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
onSaved: (input) => {players.add(Player(input))},
onDelete: f,
),
);
}
void f(Key key){
fields.removeWhere((item) => item.key == key);
}
tnx
I solved it using ListView builder
import 'package:flutter/material.dart';
import 'package:rummy/models/player.dart';
import 'package:rummy/screens/game_screen.dart';
class NewGame extends StatefulWidget {
NewGame({Key key}) : super(key: key);
#override
_NewGameState createState() => _NewGameState();
}
class _NewGameState extends State<NewGame> {
final _formKey = GlobalKey<FormState>();
List<Widget> fields;
List<Player> players;
_NewGameState() {
players = new List<Player>();
fields = new List();
print(players);
fields.add(generateField());
}
Widget generateField() {
return TextFormField(
decoration: const InputDecoration(
hintText: 'Enter Player Name',
),
onSaved: (input) => {players.add(Player(input))},
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SizedBox.expand(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
children: <Widget>[
Form(
key: _formKey,
child: Expanded(
child: ListView(
children: <Widget>[
SizedBox(
height: MediaQuery.of(context).size.height,
child: Builder(
builder: (BuildContext context) {
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: fields.length,
itemBuilder:
(BuildContext context, int postion) {
return Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: fields[postion],
),
IconButton(
icon: Icon(Icons.delete_outline),
onPressed: () => {
setState(() {
print(postion);
fields.removeAt(postion);
})
}),
],
);
},
);
},
),
)
],
),
)),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () {
print("asdasd");
if (_formKey.currentState.validate()) {
players.clear();
_formKey.currentState.save();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GameScreen(players),
));
} else
print(_formKey.currentState.validate());
},
child: Text('Submit'),
),
RaisedButton(
onPressed: () {
setState(() {
fields.add(generateField());
});
},
child: Text('Add New Player'),
),
],
),
],
mainAxisAlignment: MainAxisAlignment.center,
),
),
),
);
}
}
I used this
https://github.com/MobMaxime/Flutter-To-Do-App/blob/master/lib/screens/todo_list.dart

Add search form above Firestore list in Flutter

I am trying to render a search form above a list of items from Firestore and filter locally based on what is typed in the form.
I tried adding both widgets to the body like this, but it is only displaying the search form:
body: Column(
children: <Widget>[Searchform(), ContentWidget()],
),
This is the current code which displays a basic list:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class Items extends StatefulWidget {
Items({Key key}) : super(key: key);
#override
_ItemsState createState() => _ItemsState();
}
class _ItemsState extends State<Items> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Search'),
),
body: ContentWidget(),
);
}
}
class Searchform extends StatelessWidget {
final TextEditingController _searchController = TextEditingController();
#override
Widget build(BuildContext context) {
return TextField(
controller: _searchController,
decoration: InputDecoration(
labelText: "Search",
hintText: "Search",
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(15.0),
),
),
),
);
}
}
class ContentWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('content').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) return new Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return new Text('Loading...');
default:
return new ListView(
children:
snapshot.data.documents.map((DocumentSnapshot document) {
return new ListTile(
title: new Text(document['term']),
);
}).toList(),
);
}
},
);
}
}
What I was thinking of doing is saving the items in local state and filter them based on what is typed in the search box.
this is a very simple way try this code within "snapshot.data.documents.map((DocumentSnapshot document)"
if(_searchController.text.toString().contains(document['term'])){
return new ListTile(
title: new Text(document['term']),
);
}
I have provide simple filter record in listview code.
class FilterDemo extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return FilterState();
}
}
class FilterState extends State<FilterDemo> {
List<String> items, duplicateList;
TextEditingController editingController = TextEditingController();
#override
void initState() {
// TODO: implement initState
super.initState();
items = List<String>.generate(1000, (i) => "Item $i");
duplicateList = items;
}
void filterSearchResults(String query) {
List<String> dummySearchList = List<String>();
dummySearchList.addAll(duplicateList);
if (query.isNotEmpty) {
List<String> dummyListData = List<String>();
dummySearchList.forEach((item) {
if (item.contains(query)) {
dummyListData.add(item);
}
});
setState(() {
items.clear();
items.addAll(dummyListData);
});
return;
} else {
setState(() {
items.clear();
items.addAll(duplicateList);
});
}
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("Filter Demo"),
),
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
onChanged: (value) {
filterSearchResults(value);
},
controller: editingController,
decoration: InputDecoration(
labelText: "Search",
hintText: "Search",
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(25.0)))),
),
),
Expanded(
child: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('${items[index]}'),
);
},
),
),
],
),
);
}
}
I have provide Code how the saving the items in local state and filter them based on what is typed in the search box.
class UserList extends StatefulWidget {
final FirebaseUser user;
final String currentUserId;
UserList({this.currentUserId, this.user});
#override
_UserListState createState() => _UserListState();
}
class _UserListState extends State<UserList> {
TextEditingController _signUpConfirmPassword = new TextEditingController();
String _myValue = '';
UniqueKey _myKey = UniqueKey();
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text("UserList"),
),
child: ListView(
shrinkWrap: true,
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: CupertinoTextField(
keyboardType: TextInputType.text,
//inputFormatters: [LengthLimitingTextInputFormatter(60)],
placeholder: 'Search For..',
// placeholderStyle: TextStyle(
// fontWeight: FontWeight.w200
// ),
prefix: Padding(
padding: EdgeInsets.only(left: 10.0),
child: Icon(
Icons.search,
),
),
onChanged: (val) {
if (val.isNotEmpty) {
_myValue = val;
}
setState(() {
_myKey = UniqueKey();
});
},
decoration: BoxDecoration(
border: Border.all(color: primaryColor),
borderRadius: BorderRadius.circular(20.0)),
)),
SizedBox(height: 10.0),
Container(
key: _myKey,
child: FetchUsers(
user: widget.user,
myValue: _myValue,
)),
],
));
}
}
class FetchUsers extends StatefulWidget {
final String myValue;
final FirebaseUser user;
FetchUsers({this.myValue, this.user});
#override
_FetchUsersState createState() => _FetchUsersState();
}
class _FetchUsersState extends State<FetchUsers> {
List searchName = List();
List userName = List();
Future listOfUsers() {
if (widget.myValue.isEmpty) {
return Firestore.instance
.collection('users')
.where('Role', isEqualTo: 'user')
.orderBy('Created', descending: true)
.limit(10)
.getDocuments()
.then((d) {
userName.clear();
d.documents.forEach((f) {
userName.add(f);
});
return userName;
});
} else {
return Firestore.instance
.collection('users')
.where('Role', isEqualTo: 'user')
.limit(10)
.getDocuments()
.then((d) {
searchName.clear();
d.documents.forEach((f) {
if (f.data['Name']
.toString()
.toLowerCase()
.contains(widget.myValue.toLowerCase())) {
searchName.add(f);
}
});
return searchName;
});
}
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: listOfUsers(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CupertinoActivityIndicator(),
);
} else {
return ListView.separated(
physics: ClampingScrollPhysics(),
separatorBuilder: (context, int) {
return Divider();
},
itemCount: snapshot.data.length,
shrinkWrap: true,
padding: EdgeInsets.all(10.0),
itemBuilder: (context, index) {
return Card(
elevation: 7.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
' ${snapshot.data[index]['Name']}',
style: TextStyle(
color: outlineColor,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 5.0,
),
Text(
' ${snapshot.data[index]['Email']}',
),
],
),
Spacer(),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
RaisedButton.icon(
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(20.0)),
color: primaryColor,
onPressed: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => Chat(
user: widget.user,
name: snapshot.data[index]
['Name'],
peerId: snapshot.data[index]
['UID'],
)));
},
icon: Icon(
Icons.chat,
color: themeColor,
),
label: Text(
"Chat",
style: TextStyle(color: themeColor),
)),
RaisedButton.icon(
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(20.0)),
color: primaryColor,
onPressed: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) =>
SendNotificationOption(
name: snapshot.data[index]
['Name'],
myFcm: snapshot.data[index]
['UID'],
isBroadcast: false,
)));
},
icon: Icon(
Icons.notifications,
color: themeColor,
),
label: Text(
"Notification",
style: TextStyle(color: themeColor),
)),
],
),
],
),
),
));
},
);
}
},
);
}
}
What you have type in Search then that Data is shown in listview]1