How can i build conditions through widgets when streaming data? - flutter

I'm streaming a collection as snapshot from a firestore to my flutter project. How can i write inside a text widget e.g. 'empty' when the variable im looping doesn't exist in the collection?
child: Column(
children: <Widget>[
if (title != null)
{
Text(
title,
),
),
}
else {
Text('empty'),

You can use like below code:-
String title = '';
return Container(
child: Column(
children: <Widget>[
Text(title.isNotEmpty ? title : 'empty')
],
),
);

Related

Flutter: realtime database querying using orderbychild() and only int value works string data not querying

starCountRef.orderByChild('Series').startAt('sam').endAt('1')
This code only work if I use int values to fetch data; string values are not fetching the data.
DatabaseReference starCountRef =
FirebaseDatabase.instance.ref('/Shop/qw1234/Inventory/');
bool data = false;
Expanded(
child: FirebaseAnimatedList(
query: starCountRef
.orderByChild('Series')
.startAt('sam')
.endAt('1'),
itemBuilder: (context, snapshot, animation, index) {
return ListTile(
onTap: (() {
print(index);
}),
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Text('Price: Rs '),
Text(
snapshot.child('Price').value.toString()),
],
),
],
),
subtitle: Padding(
padding: const EdgeInsets.only(top: 10, bottom: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
'Model: ',
style: TextStyle(
fontWeight: FontWeight.bold),
),
Text(snapshot
.child('Series')
.value
.toString()),
],
),
],
),
),
);
}),
)
My firebase realtime database I am trying to setup a search box to search product and edit or delete them
Can any one help me? I am developing an inventory app for a shop. I am trying to make a search box so the owners can see their stock limits and item prices.
I rather think the firebase query works in ASCII order. In ASCII order, numbers appear before letters so starting at 'a letter string' and ending at 'a number string' is likely to cause you problems.
I don't see a '1' in your example of 'Series', you aren't trying to reference the '1' child in the 'Inventory' node are you?

In Flutter, I can't center cards in containers

return Scaffold(
body: Center(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
color: Colors.red,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Center(
child: SelectGroupCard(context, titles: titles, ids: ids,
onTap: (title, id) {
setState(() {
cardGroupResult = title + " " + id;
});
}),
),
),
],
),
There are several cards as seen in the picture. I want to get these right out. I even want to be able to show these cards in the middle of the page, in 3 columns, 4 rows.
Use widget GridView, it allows you to select the desired number of columns and rows. Also, it is possible to install paddings.
you can use GridView
GridView(
gridDelegate:const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, // you can change this
),
children :[...] // put your cards here !
)
you can remove the width property of SelectGroupCard. for example, if SelectGroupCard is a row widget, the following code like this:
Row(
mainAxisSize: MainAxisSize.min,
children: [],
)

Widget flickers and disappears when scrolling

I'm already losing sleep over this.
I'm trying to display a chart inside a ListView (for scrolling). For some reason the contents of the Card flickers when scrolling and randomly completely disappears (the Card itself stays visible though).
Any idea why would that happen?
(...) ListView (...)
children: [Row ( children: [buildChartBox()] )] (...)
Expanded buildChartBox() {
return Expanded(
child: Card(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
chartTitles(
title: 'Items',
subtitle: 'by value'),
SizedBox(
height: 300,
child: ValuesChart(data: calculateValues(items)))
],
),
],
),
),
),
);
}
Row chartTitles({String title = '', String subtitle = ''}) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: text_charttitle),
Text(subtitle, style: text_chartsubtitle),
],
)
],
);
}
Things tried:
Both of these were originally Stateless Widgets; I changed to simple
methods to simplify but it didn't change the weird behaviour.
Replacing the chartTitles return with an empty Container (i.e. removing the titles) does mitigate the issue. The chart then stays displayed but also flickers slightly.
Replacing the ListView with a SingleChildScrollView doesn't change anything.
EDIT: Code for the ValuesChart:
import 'package:fl_chart/fl_chart.dart';
class ValuesChart extends StatelessWidget {
final Map<String, int> data;
const ValuesChart({required this.data});
#override
Widget build(BuildContext context) {
return Container(
child: PieChart(
_theData(data),
));
}
}
Note I'm using a package called 'fl_chart'. _theData just returns various parameters for the chart, I don't think it's relevant.
Try to replace ListView with SingleChildScrollView
ListViews in flutter by default using what it is called in Android RecyclerView to efficiently use render resources.
If you are interested here an article
https://medium.com/1mgofficial/how-recyclerview-works-internally-71290de5d2c4

Building widgets with Hive box data

I was building my Widgets from a list that was predefined in a file of MyClass I created. This worked but I wanted to be able to store persisted data for adding a Boolean favorite field.
I created the Hive Types/Fields for my class, generated the type adapters, and successfully loaded the Hive box on first run of the app, and I can print values to the console, so I know the data is all there and correct.
In the class I have, name, image url path to asset image and a favorite field.
Before when I was using the list to get my data I was able to get the image URL like this:
Expanded(child: Image.asset(widget.MyClass.imageURL)),
Now I want to get this from the Hive box
Box<MyClass> box = Hive.box<MyClass>('myClassBox');
//This is where I am stuck
Expanded(child: Image.asset(box.???)),
I tried box.values.where and box.get() to then get to imageURL field. But get requires a key, which I don't have to pass it from
Widget build(BuildContext context)
And I then have the same issue when trying to access the favorite field, which I am using the Favorite Button package (favorite_button 0.0.4). And I will then update the true/false value based on the button being tapped.
If someone can point me in the right direction that would be great.
Thanks.
Edit:
Here is the Widget:
Widget build(BuildContext context) => GestureDetector(
onTap: () => Navigator.of(context).push(MaterialPageRoute(
builder: (context) => TaskPage(job: widget.job), //Need to get data from Hive now
)),
child: Container(
padding: const EdgeInsets.all(16),
height: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
),
child: Row(
children: [
Expanded(flex: 3, child: buildText()),
Expanded(child: Image.asset(widget.job.imageUrl)),//Need to get data from Hive now
GestureDetector(
child: Icon(
widget.job.fav ? Icons.favorite : Icons.favorite_border, //Need to get data from Hive now
),
onTap: () {
// add/remove from favorites list
}
),
],
),
),
);
Second Edit: Here is the same code after implementing the suggestion given
Widget build(BuildContext context) => GestureDetector(
onTap: () => Navigator.of(context).push(MaterialPageRoute(
builder: (context) => TaskPage(job: Hive.box<Job>('jobBox').get(context)), //This bit is still broken so I need to look at this
)),
child: Column(
children:
Hive.box<Job>('jobBox').values.toList().map(
(elementList) => Container(
padding: const EdgeInsets.all(16),
height: 100,
decoration: BoxDecoration(
color: white,
borderRadius: BorderRadius.circular(16),
),
child: Row(
children: [
Expanded(flex: 3, child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
elementList.name,
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20),
),
SizedBox(height: 10),
//Text('Num tasks in job'),
],
)),
Expanded(child: Image.asset(elementList.imageURL)),
GestureDetector(
child: Icon(
elementList.fav
? Icons.favorite
: Icons.favorite_border,
color: elementList.fav ? Colors.red.shade200 : Colors.grey,
),
onTap: () {
//To do
}
// )
),
],
),
),
)
.toList(),
),
);
Assuming that you have only 1 data in the box, you can access that stored data like this.
Box<MyClass> box = Hive.box<MyClass>('myClassBox');
if(box.isNotEmpty) {
final data = box.values.first;
// use data
} else {
// empty state
}
Hive values could have keys, depending on how you use it. If you used box.put(key, value), you can use box.get(key) to work with keys and values.
If you used box.add(value), it stores the data with auto assigned indexes starting from 0. So you can usebox.getAt(index) to get a data with index.

How to fixe itemCount to get data from firestore to list view

I have Listview.builder that contains data from an array in Firestore that an array in subcollection my structure data Like this
But when to showing that array to Listview its showing the only first, which is 0. I need to get all data In array to list view. How can I fixe itemCount to get all data?
Collcetion
-Institute
--document
---PI3naj7N7GgwlDSjK3rV0Twiu2S2
----subCollcetion
------Ravs
-------documentsubCollcetion
English
field
Ravs name :English
item array
0
Contains Data Map
1
Contains Data Map
2
Contains Data Map
.
.
.
.
this my function
StreamBuilder(
stream:Firestore.instance.collection("Institute").document(
'PI3naj7N7GgwlDSjK3rV0Twiu2S2').collection("Ravs")
.where('Ravs name',isEqualTo:'English ' ).snapshots() ,
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) return Container(
alignment: Alignment.center,
child: Text(
'it has error ',
style: TextStyle(fontSize: 12),),
);
return snapshot.hasData
? Scaffold(
appBar: new AppBar(backgroundColor: Colors.brown[600],),
body:Card(
child:ListView.builder(
itemCount:snapshot.data.documents.length,
itemBuilder: (_,index){
DocumentSnapshot ds =snapshot.data.documents[index];
return Directionality(
textDirection: TextDirection.rtl,
child:Card(
child:InkWell(
onTap: (){
},
child:Column(
children: <Widget>[
new Container(
padding: const EdgeInsets.only(top: 10),
width: 500,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(150)),
),
alignment: Alignment.topCenter,
child:
FadeInImage.assetNetwork(fit:
BoxFit.fill,placeholder:
'assets/images/image.jpg',
image: ds.data['item'][index]['Iamge path']),
),
new Container(
padding: const EdgeInsets.all(10.0),
alignment: Alignment.topRight,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(" name Rav:${ds.data['item'][index]['Ravs_name'] }",textDirection: TextDirection.rtl, style: Theme.of(context).textTheme.title),
Text("Date:${ds.data['item'][index]['Rav_Date']} ",textAlign: TextAlign.right, style: TextStyle(color: Colors.black.withOpacity(0.5))),
],
)
)
],
)
)
)
);
}
),
)
) : Center(child: CircularProgressIndicator(),);
},
);
This structure you are presenting seems to have collection in collection which is not possible. However, as this is possible to run your code, I assume that in the structure Ravs is a subcollection of documents that have field Rav name.
So the code creates query with .where('Ravs name',isEqualTo:'English '), this create snapshot of documents which I believe contains only one document. So bellow statement :
itemCount:snapshot.data.documents.length
equals to 1, and this is why you get one iteration in your itemBuilder.
I do not have any chance to test it, but I think that solution should be:
change itemCount:snapshot.data.documents[0].data['item'].length - or something like that - to give you proper number of items to iterate trough.
First line of itemBuilder should be set to: DocumentSnapshot ds =snapshot.data.documents[0]; This is because you want to iterate over array in the only one document.
If it do not work at once you should play with it... I am basing this on the fact that what you presented is possible to run :).
I hope it will help!