I have a dropdown that has lists from firebase. Now I want the selected list assign to this function. How to do that? Thanks in advance for any help.
The function:
FlutterVpn.connectIkev2EAP(
server: _addressController.text,
username: _usernameController.text,
password: _passwordController.text,
);
And this is my streamBuilder code:
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('servers').snapshots(includeMetadataChanges: true),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return Container(
child: DropdownSearch<String>(
items: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
return data["address"];
})
.toList()
.cast<String>(),
onChanged: print,
),
);
},
),
On onChanged method you need to save the actual data. And then assign it to your function:
var dataAddress;
[...]
FlutterVpn.connectIkev2EAP(
// here use it
server: dataAddress,
username: _usernameController.text,
password: _passwordController.text,
);
[...]
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('servers').snapshots(includeMetadataChanges: true),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return Container(
child: DropdownSearch<String>(
items: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
return data["address"];
})
.toList()
.cast<String>(),
onChanged: (var data) {
// here save the info
dataAddress = data;
},
);
},
),
Related
I have 3 dropdown that has lists from firebase. The flowchart of my program is when I choose the address, so the username and password are automatically selected according to the address that has been selected. This is my code:
StreamBuilder 1
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('servers').snapshots(includeMetadataChanges: true),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return Container(
child: DropdownSearch<String>(
items: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
return data["address"];
})
.toList()
.cast<String>(),
onChanged: print,
),
);
},
),
StreamBuilder 2
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('servers').snapshots(includeMetadataChanges: true),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return Container(
child: DropdownSearch<String>(
items: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
return data["username"];
})
.toList()
.cast<String>(),
onChanged: print,
),
);
},
),
StreamBuilder 3
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('servers').snapshots(includeMetadataChanges: true),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return Container(
child: DropdownSearch<String>(
items: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
return data["password"];
})
.toList()
.cast<String>(),
onChanged: print,
),
);
},
),
And this is my firebase database:
I've tried to write those code inside children: <Widget>[] but the data can't showed in my app.
Thank you in advance for any help.
Dropdowns are usually used as static data so if you are keeping that data in firebase. It would be better to fetch this data in a list in initState method and then use in the StreamBuilder instead of fetching it in StreamBuilder
hey i am new too flutter, i want to create combined filter screen alike in a e commerce app,for example product will have 3 field Brand,price range,size,i want to display data from firebase snapshot by combining, brand ,price and size
stream:
FirebaseFirestore.instance.collection("users").snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
final brandss = FirebaseFirestore.instance
.collection('users')
.where('name', isEqualTo: 'zara')
.snapshots();
if (snapshot.hasData && snapshot.data != null) {
return Expanded(
child: ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
Map<String, dynamic> userMap =
snapshot.data!.docs[index].data()
as Map<String, dynamic>;
return ListTile(
leading: CircleAvatar(
backgroundImage:
NetworkImage(userMap["profilepic"]),//image
),
title: Text(
userMap["brand"] + " (${userMap["price"]})"),
subtitle: Text(userMap["email"]),
trailing: IconButton(
onPressed: () {
// Delete
},
icon: Icon(Icons.delete),
),
);
},
),
);
} else {
return Text("No data!");
}
``` please help me with logic
you can try to filter 3 conditions with multiple where
FirebaseFirestore.instance.Collection('product').where('Brand', isEqualTo:Brand).where('price', isLessThanOrEqualTo: maxPrice).where('price', isGreaterThanOrEqualTo: minPrice).where('size',isEqualTo:size)
I am developing an android application with flutter, what I am doing is displaying a json in an application page. When I run the application it doesn't give me an error but it doesn't show me the data, the json I want to read is the following:
[
{
"deviceid": 27,
"f2cuid": "Estacion1_A",
"devicedata": {
"isRunning": 0,
"color": "w3-red",
"colorNoW3": "red",
"device_name": "Estacion1_A"
}
},
{
"deviceid": 20,
"f2cuid": "B19",
"devicedata": {
"isRunning": 1,
"color": "w3-green",
"colorNoW3": "green",
"device_name": "B19"
}
}
]
It's in my model class:
class Stations {
Int? isRunning;
String? color;
String? colorNoW3;
String? devicename;
Stations(
{this.isRunning,
this.color,
this.colorNoW3,
this.devicename,
});
factory Stations.fromJson(Map<String, dynamic> json) {
return Stations(
isRunning: json['isRunning'],
color: json['color'],
colorNoW3: json['colorNoW3'],
devicename: json['device_name'],
);
}
}
This is my service:
Future<List<Stations>> getStations() async {
Uri url = Uri.parse('URL');
final response = await http.get(url);
var data = jsonDecode(response.body);
print('data: $data');
List<Stations> stations = data.map((e) => Stations.fromJson(e)).toList();
return stations;
}
and this is the way I display it:
return Scaffold(
appBar: AppBar(
title: const Text('Sistema Escolar Administrativo'),
),
drawer: DrawerWidgetMenu(),
body: Container(
child: FutureBuilder(
future: stationSvc.getStations(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Container(
child: Center(
child: Text('No hay datos que mostrar'),
),
);
}
return snapshot.data.length > 0
? ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: InkWell(
onTap: () {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) => HomePage(),
),
);
},
child: ListTile(
leading: Text(snapshot.data[index].devicename!),
title: Text(snapshot.data[index].color!),
subtitle: Text(snapshot.data[index].colorNoW3!),
),
));
})
: Center(
child: Text('No hay datos, registra un grupo primero'));
}),
),
);
You forgot to specify nested map:
factory Stations.fromJson(Map<String, dynamic> json) {
return Stations(
isRunning: json['devicedata']?['isRunning'],
color: json['devicedata']?['color'],
colorNoW3: json['devicedata']?['colorNoW3'],
devicename: json['devicedata']?['device_name'],
);
}
I am sharing a complete class named SampleModel below which can help to parse JSON in flutter:
class SampleModel {
String? _myName;
bool? _isActive;
SampleModel({String? myName, bool? isActive}) {
if (myName != null) {
_myName = myName;
}
if (isActive != null) {
_isActive = isActive;
}
}
String? get myName => _myName;
set myName(String? myName) => _myName = myName;
bool? get isActive => _isActive;
set isActive(bool? isActive) => _isActive = isActive;
SampleModel.fromJson(Map<String, dynamic> json) {
_myName = json['myName'];
_isActive = json['isActive'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['myName'] = _myName;
data['isActive'] = _isActive;
return data;
}
}
Sample JSON for the same class:
{
"myName" : "Your Name",
"isActive" : true
}
Check if this can help in your case.
your json type is an array, not a map.
look at [ ] syntax on json file.
to deal with an Array, you should make it to a list first:
List<Map<String,dynamic>> mylistofMapformJson = json.decode(receivedJson);
//you should get your list stations like this:
List<Stations> listStationsFromJson = List.generate(
mylistofMapformJson.length,
(index) => Stations.fromJson(mylistofMapformJson));
I want to make a to-do list with task due date as an optional field, so I need to check if some tasks have dueDate and add it as a subtitle based on that. How can I check if a field exists inside a doc in a StreamBuilder?
class _TaskListState extends State<TaskList> {
var myStream;
#override
void initState() {
myStream = FirebaseFirestore.instance
.collection('tasks')
.doc(widget.uid)
.collection('mytasks')
.snapshots();
super.initState();
}
...
void _updateTaskDesc(
dynamic currTask, String newDesc, DateTime newDate, TimeOfDay newTime) {
FirebaseFirestore.instance
.collection('tasks')
.doc(widget.uid)
.collection('mytasks')
.doc(currTask['id'])
.update({
'desc': newDesc,
'dueDate': newDate.toString(),
'dueTime': newTime.toString(),
});
}
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: myStream,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: SizedBox(
height: 100, width: 100, child: CircularProgressIndicator()),
);
} else {
final docs = snapshot.data.docs;
bool hasDateTime = ????? <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
return ListView.builder(
itemCount: docs.length,
itemBuilder: (ctx, index) {
final currTask = docs[index];
return InkWell(
highlightColor: Theme.of(context).secondaryHeaderColor,
splashColor: Theme.of(context).secondaryHeaderColor,
onLongPress: () {
showModalBottomSheet<dynamic>(
isScrollControlled: true,
context: context,
builder: (bCtx) {
FocusManager.instance.primaryFocus?.unfocus();
return TaskOptions(_updateTaskDesc,
() => _updateHasImage(docs[index]), currTask);
},
);
},
child: Dismissible(
direction: DismissDirection.startToEnd,
key: UniqueKey(),
onDismissed: (_) async {
FirebaseFirestore.instance
.collection('tasks')
.doc(widget.uid)
.collection('mytasks')
.doc(currTask['id'])
.delete();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text("${currTask['desc']} dismissed"),
action: SnackBarAction(
label: 'Undo',
onPressed: () {
FirebaseFirestore.instance
.collection("tasks")
.doc(widget.uid)
.collection("mytasks")
.doc(currTask['id'])
.set({
"desc": currTask['desc'],
"id": currTask['id'],
"isDone": currTask['isDone'],
"hasImage": currTask['hasImage'],
});
try {
FirebaseFirestore.instance
.collection("tasks")
.doc(widget.uid)
.collection("mytasks")
.doc(currTask['id'])
.update({
"dueDate": currTask['dueDate'],
"dueTime": currTask['dueTime'],
});
} catch (e) {}
},
),
),
);
},
child: ListTile(
...
subtitle: Text(hasDateTime
? DateFormat('dd/MM')
.format(DateTime.parse(currTask['dueDate']))
: ''),
...
I saw that a containsKey('key') method works for some people but I get NoSuchMethod when I try that. What can I do?
The single document is just a normal Dart Map, so you can check if a key exists or not using containsKey method.
So you condition becomes the following:
bool hasDateTime = currTask.containsKey('dueDate`);
NOTE: In the question I can see that you are defining the condition in the wrong place which is outside the itemBuilder method in the ListView so that it is not item based and well not work because it does not make sense.
You can have it in this place:
...
itemBuilder: (ctx, index) {
final currTask = docs[index];
bool hasDateTime = currTask.containsKey('dueDate`);
return InkWell(
...
Can someone explain me why the productlist variable is null when this class run? It loooks like the variable is being populated after the first istance end, so the CardShopList widget hasn't the productlist that is coming from the nested istance.
Have you got some tips? Thanks!
Future getMyShopLists(User user) async {
List<Widget> listItems = [];
FirebaseFirestore.instance
.collection('user')
.doc(user.uid)
.collection('shoplist')
.get()
.then((event) {
event.docs.forEach((shoplist) {
List<ProductModel> productlist = [];
Map shopListData = shoplist.data();
shoplist.reference.collection('productlist').get().then((element) {
Map productData = shoplist.data();
element.docs.forEach((doc) {
productlist.add(ProductModel(
id: doc.id,
name: productData['name'],
quantity: productData['quantity'],
price: productData['price'],
));
});
});
listItems.add(CardShopList(
shoplist.id,
shopListData['name'],
productlist, // <------------------------------- THIS IS NULL!!!!
getMyShopLists,
key: ValueKey<String>(shoplist.id),
));
});
if (this.mounted) {
setState(() {
shopListsWidget = listItems;
});
}
});
return shopListsWidget;
}
EDIT i use that class in this FutureBuilder :
FutureBuilder(
future:
searchIcon.icon == Icons.search ? getMyShopLists(user) : null,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return isShopListEmpty
? new Center(
child: new Text(
"x",
style: TextStyle(fontSize: 20),
textAlign: TextAlign.center,
),
)
: Container(
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: shopListsWidget.length,
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) {
return shopListsWidget[index];
}))
],
),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
The "productlist" is not expected to be filled because you are using foreach. There may be alternative solutions, but turning foreach to for will probably fix it.
...
await FirebaseFirestore.instance //added await
.collection('user')
.doc(user.uid)
.collection('shoplist')
.get()
.then((event) async{ //added async
for(QueryDocumentSnapshot shoplist in event.docs){ //---this line changed
List<ProductModel> productlist = [];
Map shopListData = shoplist.data();
await shoplist.reference.collection('productlist').get().then((element) //added await
{
Map productData = shoplist.data();
for(QueryDocumentSnapshot doc in element.docs) //---this line changed
{
productlist.add(ProductModel(
id: doc.id,
name: productData['name'],
quantity: productData['quantity'],
price: productData['price'],
));
}
});
listItems.add(CardShopList(
shoplist.id,
shopListData['name'],
productlist,
getMyShopLists,
key: ValueKey<String>(shoplist.id),
));
}
...
Keep in mind I did not tested this, but I had previous issues with that.
My suggestion is to move this block of code:
listItems.add(CardShopList(
shoplist.id,
shopListData['name'],
productlist, // <------------------------------- THIS IS NULL!!!!
getMyShopLists,
key: ValueKey<String>(shoplist.id),
));
Inside the firebase query like so:
shoplist.reference.collection('productlist').get().then((element) {
Map productData = shoplist.data();
element.docs.forEach((doc) {
productlist.add(ProductModel(
id: doc.id,
name: productData['name'],
quantity: productData['quantity'],
price: productData['price'],
));
});
listItems.add(CardShopList(
shoplist.id,
shopListData['name'],
productlist,
getMyShopLists,
key: ValueKey<String>(shoplist.id),
));
});
The reason for the null value is that the firebase query has a local variables and they exist only for the moment of the request. The only way to work with them is locally in the query callback.
You're defining it as an async function, but didn't await for the queries to be processed in order, can you try adding await in these locations:
//here #1
await FirebaseFirestore.instance
.collection('user')
.doc(user.uid)
.collection('shoplist')
.get()
.then((event) async {
event.docs.forEach((shoplist) {
List<ProductModel> productlist = [];
Map shopListData = shoplist.data();
//here#2
await shoplist.reference.collection('productlist').get().then((element) {
Map productData = shoplist.data();
element.docs.forEach((doc) {
productlist.add(ProductModel(
id: doc.id,
name: productData['name'],
quantity: productData['quantity'],
price: productData['price'],
));
});
});