Flutter - Sending SQL data to a ListView - database

Using the flutter package sqflite I've managed to save data from a news source to a database, such as title, description and more.
Please take the time to look at this application created database file that follows my structure.
This is how I create the database, and how I save data to it from an online source.
var title = articles[index].title;
var description = articles[index].description;
var url = articles[index].url;
var urlToImage = articles[index].urlToImage;
var publishedAt = articles[index].publishedAt;
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'saved_articles.db');
Database database = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
// When creating the db, create the table
await db.execute(
'CREATE TABLE Article (id INTEGER PRIMARY KEY, title TEXT, description TEXT, url TEXT, urltoimage TEXT, publishedat TEXT)');
});
print(database);
print(databasesPath);
// Insert some records in a transaction
await database.transaction((txn) async {
int id1 = await txn.rawInsert(
'INSERT INTO Article(title, description, url, urltoimage, publishedat) VALUES("$title", "$description", "$url", "$urlToImage", "$publishedAt")'
);
debugPrint('inserted1: $id1');
});
I'm looking for a method in which to send this data straight to an ordered ListView. The end goal for this being a favourites page which saves articles to the user's device for offline viewing.
This is how I'm retrieving specific data for converting into the bottom title list.
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'saved_articles.db');
Database database = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
// When creating the db, create the table
await db.execute(
'CREATE TABLE Article (id INTEGER PRIMARY KEY, title TEXT, description TEXT, url TEXT, urltoimage TEXT, publishedat TEXT)');
});
List<Map> title = await database.rawQuery('SELECT title FROM Article');
List<Map> description = await database.rawQuery('SELECT description FROM Article');
List<Map> url = await database.rawQuery('SELECT url FROM Article');
This is what I'm using to send specific queries to list, but I'm not sure where to go from here in terms of creating a viable structure for sending this data to the desired ListView
List<Map> title = await database.rawQuery('SELECT title FROM Article');
Thanks

I'm not entirely sure I understand your question or issue, so please follow up if I'm missing something.
I'm looking for a method in which to send this data straight to an ordered ListView.
From this, I understand your question as you are just wondering what to do next in flutter?
If so, I would recommend taking a look at: https://pub.dartlang.org/packages/jaguar_serializer
Then here's what I would do
Create an Article model, following jaguar's readme OR just make a manual function to convert a map to an instance of Article.
import 'package:jaguar_serializer/jaguar_serializer.dart';
part 'article.jser.dart';
class Article {
string title;
string description;
string url;
etc...
}
etc..
Run the cli tool
Create a query to get a List of all articles, such as (ordering in sql is faster)
'SELECT title, description, url FROM Article ORDER BY title'
Map that to a list of articles (again take a look at jaguar readme for creatont a JsonRepo.
List<Article> articles = jsonRepo.decodeList<Complete>(response.body);
Then you can just pass in your articles to the ListView in flutter.
ListView.builder(
padding: EdgeInsets.all(8.0),
itemExtent: 20.0,
itemBuilder: (BuildContext context, int index) {
return Text('entry ${articles[index].title}');
},
)

Related

Firestore: How to map data, to an array, from a document that contains an array of maps?

I am self taught and very new, so please excuse any dumb questions.
I am trying to fetch a stored document using getDoc, map that data to an array, and use that array as data in a table. I believe I correctly stored my data as a document that contains an object(dataExcel) that contains an array of maps in Firestore.
const submitGrades = async () => {
await setDoc(doc(db, 'EventData', 'Game 1' + ' PlayData'), {dataExcel})
await setDoc(doc(db, "EventData", 'Game 1' + ' PlayerData'), {playerData})
}
I know that this isn't ideal for complex querying, but it works for me as I have no problem pulling the entire document anyway. Then using JavaScript to sort the data the way I want. I am able get the document successfully using:
const Fetch = async () => {
const dataRef = doc(db, 'EventData', 'Game 1 PlayData');
const data = await getDoc(dataRef);
console.log(data);
}
, however I can't figure out how to pull out the array of maps, set them in state and make them usable as data in a table.
My current data structure
I need it to look like this once passed to a table:
enter image description here

Create bd in android - flutter

I was trying to create a local DB but I'm having some problems, this is my code
Future<Future<Database>> createTable() async {
WidgetsFlutterBinding.ensureInitialized();
final database = openDatabase(
join(await getDatabasesPath(), 'doggie_database.db'),
onCreate: (db, version) {
return db.execute(
'CREATE TABLE dogs(id INTEGER PRIMARY KEY, ref TEXT, descricao TEXT, name TEXT, price DOUBLE, quantity DOUBLE, image TEXT, cor TEXT, tamanho TEXT, priceWithoutTax DOUBLE)',
);
},
version: 1,
);
return database;
}
Future<void> insertDog(Dog dog) async {
var db = await createTable();
await db.insert(
'dogs',
dog.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
that is, I'm creating the DB when I call the insertDog. At first I tried to create the DB in main but then I couldn't call the "database" . So I decided this way, now I can't continue because "await db.insert" is giving error.
erro:"The method 'insert' isn't defined for the type 'Future'.
Try correcting the name to the name of an existing method, or defining a method named 'insert'."
I don't know if there is a solution to this problem or if anyone has another suggestion.
thanks

Fetch Data in a collection in a root collection Firebase Web SDK 9

I have a table of Firestore database. When I click to one content, it will lead to the detailed page of that content. The illustrated image is displayed below:
Table of "reports"
Detailed page of each report
In logical, I have a collection named "reports". It contains a lot of documentations. When I select a specific content, I have already fetch all the data(field) inside each document(content). However, I have one field with format of collection(named "comments"). So could you please to guide me how to fetch all the data in "comments". Noted that some report does not have field "comments".
"report" collection
"comments" collection
Some report does not have field "comments" when field "totalCom" = 0
Report does not have comments
Here is my code when I fetch data in each report":
Link to the detailed page
<Link to={`/view/${currentItem.id}`}
Fetch data from each report
useEffect(() => {
const fetchDocById = async () => {
const docRef = doc(db, "reports", id)
const docSnap = await getDoc(docRef)
if (docSnap.exists()) {
setUser({
...docSnap.data()
});
} else {
setUser({});
}
}
fetchDocById()}, [id]);
All my code are compatible with Web JDK v9.
I really appreciate for all your time and support!

Query through all documents in a collection, and through all subcollections in firestore

I am building an app using Firebase Firestore as a BaaS.
But I am facing a problem when I try to create a feed/implement full-text-search on my app.
I want to be able to search through all the users posts, the problem is, the users posts are structured like this in the Firestore Database:
Posts(collection) -> UserID(Document) -> user posts(subcollection that holds all userID posts) -> actual posts(separate documents within that collection)
I want to loop through every user's user posts subcollection and fetch all data for the feed, and also to implement it with a full text search app like Algolia or ES.
I can loop through a specific user ID(code below), but being a beginner, I couldn't find a way to loop through all of them and fetch all of them.
firebase.firestore()
.collection('allPosts')
.doc('SPECIFIC_USER_ID') //-> Here I have to loop through all docs in that collection
.collection('userPosts')
.orderBy("creation", "asc")
.get()
.then((snapshot) => {
let posts = snapshot.docs.map(doc => {
const data = doc.data();
const id = doc.id;
return { id, ...data }
})
setUserPosts(posts)
})
}
Would love some help!
Collection Group Query
You can query in all collections named X using a collection group query.
var posts= db.collectionGroup('userPosts').orderBy('creation').limit(10);
posts.get().then((querySnapshot) => {
let posts = querySnapshot.map(doc => {
const data = doc.data();
const id = doc.id;
return { id, ...data }
})
setUserPosts(posts)
});
Source: https://firebase.google.com/docs/firestore/query-data/queries#collection-group-query
Algolia implementation
You will need to use Cloud Functions to migrate fields to a dedicated collection specifically for Algolia. Many users have found nested SubCollections to be problematic with Algolia's setup.
You do this by duplicating the user Post data as a 'source' to this new public collection, and using the Firebase Algolia Extension, you can sync it directly
exports.bakePosts= functions.firestore
.document('allPosts/{userID}/userPosts/{postID}')
.onWrite((change, context) => {
// Get an object with the current document value.
// If the document does not exist, it has been deleted.
const document = change.after.exists ? change.after.data() : null;
// Get an object with the previous document value (for update or delete)
const oldDocument = change.before.data();
if(document != null)
db.collection("posts/"+ context.params.postID).set(document);
if(document == null)
db.collection("posts/"+ context.params.postID).delete();
});
Algolia Extension:
https://firebase.google.com/products/extensions/firestore-algolia-search
You can avoid most of the above if you simply submit posts to a master collection and have the userID as the 'owner' property within the document. The above also have benefits, but more related to blog posts where users may have a "work in progress" version vs Live.
The Algolia Extension has the full guide on how to set it up and if you need to customize the extensions, the source code is also available.

How to get current auto generated document ID during posting with cloud firestore in flutter?

I'm posting a post of location with firestore and save their data to the database on button click.
Every button click it's generating auto DocumnetID and want to save this ID to the database in same time.
Code:
await firestore.collection("Table_Name").document().setData({
"SpotLatLong":new GeoPoint(spotlat, spotlong) ,
"spotName": placeNameController.text,
"SpotImage":spotImage,
"UserID":uid,
"SpotActivity":spotActivity,
"SpotDocumentID": firestore.collection("Table_Name").document().documentID.toString()//this line generates Different documentID, which is wrong
}).then((onValue){
StyleWidget.showToast(msg: "Created spot to the table");
Navigator.pop(context);
isLoading = false;
});
String id= await firestore.collection("Table_Name").document().documentID().toString;
await firestore.collection("Table_Name").document(id).setData({
"SpotLatLong":new GeoPoint(spotlat, spotlong) ,
"spotName": placeNameController.text,
"SpotImage":spotImage,
"UserID":uid,
"SpotActivity":spotActivity,
"SpotDocumentID":id //this line generates Different documentID, which is wrong
}).then((onValue){
StyleWidget.showToast(msg: "Created spot to the table");
Navigator.pop(context);
isLoading = false;
});
Hope help this
To have to programatically add the new Document to document id as followind,
// Your Firestore Database Reference
var tableReference = Firestore.instance.collection("Tables");
// Push a new ID every time like this
var ID = groupReference.document().documentID;
// Set Data to the new Document ID
await firestore.collection("Table_Name").**document(ID)**.setData({
"SpotLatLong":new GeoPoint(spotlat, spotlong) ,
"spotName": placeNameController.text,
"SpotImage":spotImage,
"UserID":uid,
"SpotActivity":spotActivity,
"SpotDocumentID": firestore.collection("AddSpot").document().documentID.toString()//this line generates Different documentID, which is wrong
}).then((onValue){
StyleWidget.showToast(msg: "Created spot to the table");
Navigator.pop(context);
isLoading = false;
});
var docRef = await firestore.collection("Table_Name").document().setData({
"SpotLatLong":new GeoPoint(spotlat, spotlong) ,
"spotName": placeNameController.text,
"SpotImage":spotImage,
"UserID":uid,
"SpotActivity":spotActivity,
"SpotDocumentID": firestore.collection("AddSpot").document().documentID.toString()//this line generates Different documentID, which is wrong
}).then((onValue){
StyleWidget.showToast(msg: "Created spot to the table");
Navigator.pop(context);
isLoading = false;
});
Get document reference by this way
docRef.documentID

Resources