Mobile apps need a backend. They store settings & data, high scores, check licenses and generate statistics. All these use cases have one thing in common: they use a central database.

Coding a full-blown backend takes a lot of time. Think about end-to-end security, communication interfaces and database structure. When you then get to details like concurrent access, it gets tricky.

Luckily, Google Firebase takes care of all these issues for you. It’s a ready-to-use cloud-hosted database with full authentication support. In contrast to a traditional SQL database, Google Firebase stores JSON data sets (-> NoSQL). This gives you more flexibility in your data structure.

On top of that, you can subscribe to real-time data changes. You’ll get notified about updates made to the data, for example by other users. The service does offer a simple REST API. But the most efficient communication is a publish & subscribe model via websockets.

That sounds complicated? Google offers a separate SDK for each platform. With Felgo & Qt, you don’t need to worry about platform differences. Felgo includes a cross-platform Google Firebase Realtime Database plugin. The same QML / JavaScript-based API works for both Android & iOS.

If you need help with that, consult or outsource your app development with Felgo.

Getting Started

In this Firebase tutorial, you’ll complete the full journey from start to end. You start with a project template of Qt Creator. Next, you’ll set up the Firebase service in the cloud. Another important task is user authentication. Most impressive: live database updates from & to your cross-platform app.

Firebase-Create-Entry

The scenario is a simple shopping list. It’s a generic app that includes everything most apps need. Authentication, plus adding, updating and deleting items. Once you understand the concepts, it’s easy to adapt them to your own scenario.

If you’re impatient, skip right to the final project source code on GitHub.

Watch this Tutorial on YouTube

You can also watch the video version of this tutorial on YouTube. It is very much in-depth and covers every single step of the process.

Master-Detail UI for your Cloud Backend

Curious to dive right into the cloud database? Well, you will need your “app package name” for Android and the “iOS bundle ID” when setting up Firebase.

Thus, start with the app and make your life easier. Open Qt Creator and create a new project. Use the “Felgo Apps” > “Master-Detail Application”. This gives you great boilerplate code for any list-type app.

master-detail-app-wizard

In step 2, choose the kits for the target platforms: Android and/or iOS.

Take special note of the “Felgo Project Properties” page (step 3). Here, you define the app identifier, which you will also need for the Firebase setup. In this case, choose com.vplay.ShoppingList.

new-app-wizard-3-project-properties-app-identifier

Google offers different Firebase samples for individual platforms & tools. With Felgo, you run the same code across Android & iOS. Activate the “Google Firebase” plugin. It includes ready-made cross-platform code to interact with the Google cloud!

new-app-wizard-4-google-firebase-support

Live Testing on Android & iOS

If you target both Android and iOS, you’ll want to test your app on both platforms. Felgo Live immediately deploys and executes any code changes on any connected phone. You can even connect and test on iOS phones while developing on Windows. You save an incredible amount of time: no more re-building, deploying and testing.

v-play-live-run-button

To get started, download the Felgo Live app from the app store: Android / iOS. Next, make sure your development computer and the phone are on the same local network. Start the Felgo Live app on your phone and connect it to your Live Server. If your Live Server is not running yet, click on “Live Run” in Qt Creator, to start developing with live code reloading!

Felgo Plugin License

Your app currently shows a watermark that you’re running a trial of the Firebase plugin. That’s fine for your first testing steps! To get rid of the trial watermark and the license reminders, you need the Felgo Indie license. If you do not have an Indie license, you can continue using the Firebase plugin in trial mode, without generating a license key.

Authorization works through a license key for your app. Go to https://felgo.com/upgradeLicense. Select the “Google Firebase” plugin. Next, click the green “Generate License Key” button at the bottom of the page.

firebase-plugin-license

Next, enter your app identifier (e.g., “com.vplay.ShoppingList”). The suggested version “1” is correct – it’s the default in every new project.

v-play-license-key

Copy the new license key to your code, add it to the licenseKey property in your Main.qml file. The watermark disappears. This video shows the original Master-Detail sample app. When inserting the license key to the code, the app instantly reloads – without the watermark. Afterwards, you see a brief demo of the initial app functionality.

mater-detail-app-add-license-key

Create the Firebase Project

Congratulations, your master-detail app is running on the phone! Now, it’s time to create the Google Firebase Realtime database. This serves as complete lightweight backend for the shopping list example app.

To create a Firebase account, go to the Firebase homepage. Login with your Google Account to see the empty console. The project you create runs great with the free account. You don’t need to worry about payments.

First, click on “Add project”.

firebase-console-new-project

Give your project a name to recognize it in your console: “ShoppingList”. The “Project ID” is auto-generated with a number, as it needs to be globally unique. You can customize the ID if you like. Note that your users will never see this ID, though – so don’t spend too much time here.

firebase-new-project-wizard-shoppinglist

Click on “CREATE PROJECT”. In a few seconds, the project dashboard greets you with the overview:

firebase-dashboard-shoppinglist-qt

Connect Your App to Firebase

Your shopping list app stores the items in the cloud. Grant your app access to the Firebase project. Click on the big circle for your target platform: iOS or Android.

Enter the package name again. The optional “app nickname” is only for internal use inside your dashboard.

firebase-register-android-app

The Firebase wizard now prompts to download the config file. Download this file and store it somewhere on your computer.

firebase-console-new-project-config-file

The major parts of the config file look like this. They contain all the information you need to connect your app to Firebase.

{
"project_info": {
"project_number": "766025596428",
"firebase_url": "https://shoppinglist-vplay.firebaseio.com",
"project_id": "shoppinglist-vplay",
"storage_bucket": "shoppinglist-vplay.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:766000006428:android:a28d200000001c88",
"android_client_info": {
"package_name": "com.vplay.ShoppingList"
}
},
"api_key": [
{
"current_key": "AIzaSyCvAzxxxxxxxxxxxxxxxxxEXg-cv8TikY0"
}
]
}
],
"configuration_version": "1"
}

For your Felgo project, you could use this config file. But it’s easier to copy the API keys to the plugin config, as you will see below. So, skip steps 3 + 4 of the Firebase wizard.

In Qt Creator’s “Projects” view, right-click the “qml” folder. Select “Add new…”. Choose the “Felgo Apps” -> “Item” template.

firebase-data-model

In the following “Item details” dialog, enter:

  • File name: DataModel
  • Path: create a new sub-folder in your project’s qml folder, called “model”

The generated file is almost empty. Change the default generated ID from “item” to “dataModel”. As you are using the Firebase plugin, add the following line to the import section at the beginning of the file:

import Felgo 3.0

The FirebaseConfig QML element encapsulates all connection settings – for both Android and iOS. Add it to your item. Your data model now looks like this:

import QtQuick 2.0
import Felgo 3.0

Item {
id: dataModel

FirebaseConfig {
id: fbConfig

projectId: "<your project ID, from project_info | project_number, e.g., 82701038584 or shoppinglist-vplay>"
databaseUrl: "<your database URL, from project_info | firebase_url, e.g.,: https://shoppinglist-vplay.firebaseio.com>"

apiKey: Qt.platform.os === "android"
? "<your Android API key, from client | api_key | current_key>"
: "<your iOS API key>"

applicationId: Qt.platform.os === "android"
? "<your Android application ID, from client | client_info | mobilesdk_app_id>"
: "<your iOS application ID>"
}
}

Firebase Database Setup

Your app will store a list of items in the database. Firebase is a JSON-based NoSQL database. What does it do?

This is what your database will look like:

database-structure

The database is a tree of items. Each can have children and any structure. That makes the database much more flexible than tables in traditional SQL.

Some of the structure is pre-defined by Firebase; some is coming from your app. A quick overview, before you dive in:

  1. shoppinglist-vplay: the root node of the entire database (shown in yellow).
  2. users: each user is going to have a private shopping list. After all, you don’t want to buy items that a stranger added, right? Thus, the next node is “users”. It contains a list of user UIDs. The database itself doesn’t store any further information about the user’s identity. You can look this up in the “Authentication” section of your Firebase project dashboard:
    firebase-authentication-user-list
  3. shoppinglist-user: the root node of the individual shopping list. This is what a logged-in user sees. It contains several items, one for each item to buy. Here, it’s currently milk and apples.

Create the Cloud Database

In your browser, return to the Firebase dashboard. Select “Database” on the left. Next, click on “Get Started” in the “Realtime Database” block. The Cloud Firestore is currently still in beta. That’s why it’s not recommended for production use yet. We will take a closer look in a future tutorial.

firebase-create-new-realtime-database

Next up is the “Security rules for Realtime Database” dialog. It’s a good idea to start with proper authentication right away, instead of plugging it in later.

Firebase Authentication

Your app needs to recognize, differentiate and securely authorize users. The Firebase Authentication service makes this easy. It supports multiple authorization providers: Facebook, Google Account, Twitter, GitHub and even a phone-based user authentication per SMS.

Firebase even lets you use “anonymous” authentication. This means the user does not have to do any authentication step in order to use the Firebase Database.

To get started, we will use the Email / Password variant. Firebase takes care of managing users and even supports sending password reset emails.

To activate it, go to the Authentication section (1) of your Firebase dashboard.

firebase-authentication-sign-in-provider

Next, choose “Sign-In Method” (2). Click on “Email/Password” (3) to expand this section. Enable it (4) and save the changes (5). In the “Templates” section, you could further customize the behavior. E.g., a custom confirmation email text when a user signs up.

Firebase Login from Your Client App: Architecture

Felgo simplifies the authentication process. The engine includes a predefined item FirebaseAuth that handles the cloud communication.

The app architecture is clear:

  • The App is the main QML item that owns all the other items and ensures they communicate with each other
  • DataModel is a direct child of the App. It is a layer that handles the authentication and shopping items (your data). It abstracts the Google Firebase. The rest of your application does not need to worry about the backend or any cloud communication.
    Its onLoggedIn slot triggers navigating from the LoginPage to the ShoppingListPage.

     

    • FirebaseAuth is an item provided by Felgo. It communicates with the Firebase cloud. It provides convenient signals and slots. These integrate the relevant events into your app.
    • FirebaseConfig is what we’ve already created. It contains basic settings, like the API key, configuration, …
  • NavigationStack handles all the visible pages.
    • LoginPage is initially visible. It contains the user interface to enter username and password. Plus, you can trigger new user registrations for the Firebase backend.
      Its onLogin slot executes when the user taps the button to login / register.
    • ShoppingListPage shows all the shopping items, which you’ll retrieve from the Firebase database. It is only visible after successful authentication.

Google-Firebase-Authentication-Architecture-Qt-Qml

Firebase Authentication: Callbacks from the Cloud

You start by adding the FirebaseAuth item to your DataModel. It is simple to use: assign an ID and give it a reference to the config item you created before. Also, add two signals (“loggedIn”, “loggedOut”) to your DataModel. They inform the app about the user’s login status.

signal loggedIn
signal loggedOut

FirebaseAuth {
id: auth
config: fbConfig

onLoggedIn: {
if(!success) nativeUtils.displayMessageBox(qsTr("Login failed"), qsTr("Reason: %1").arg(message), 1)
}
onUserRegistered: {
if(!success) nativeUtils.displayMessageBox(qsTr("Register failed"), qsTr("Reason: %1").arg(message), 1)
}

onAuthenticatedChanged: if(authenticated) dataModel.loggedIn()
}

FirebaseAuth offers three important slots for reacting to cloud responses:

  1. onLoggedIn: fired after the loginUser request has finished. This is a good place for you to check if there was an issue with the login.
  2. onUserRegistered: like the login, but for a finished registerUser request.
  3. onAuthenticationChanged: the most important status change: is the user logged in? With this generic slot, your app is flexible no matter how the user logged in. All that matters is if he is logged in at the end. In that case, our DataModel emits the loggedIn signal to let the app switch to the main data model page.

Firebase: Triggering Login, User Registration and Logout

Now, your app already handles the status change responses coming from Firebase. But, you still need to trigger the login! The FirebaseAuth item includes convenient methods for triggering authentication tasks.

Your DataModel.qml encapsulates the communication with Firebase. So, you include simple methods that forward the requests to Firebase.

function registerUser(email, password) {
auth.registerUser(email, password)
}

function loginUser(email, password) {
auth.loginUser(email, password)
}

function logoutUser() {
// logout is instant and always works (there is no callback)
auth.logoutUser()
}

You might wonder why you should do this. After all, the new methods are an exact replica of the existing. Once you expand your app, you might want to surround these calls with extra checks. E.g., you could test if the email address is valid. So, it’s a good idea to think of a good architecture right from the start.

Firebase Login Flow in the App

The example app already includes two sample pages for Firebase, which we will not use however. They are a concise essence of what you can do with Firebase. In our sample, we use Firebase as part of the complete app architecture.

Create a new page: LoginPage.qml. It’s will be a simple page with 2 text boxes and a button. A checkbox switches between login and new user registration. Copy the source code from the GitHub sample into your new page.

Important for the concept is that the page emits a signal once the user taps the button: “login(bool isRegister, string email, string password)”. The parameters include everything Firebase needs to perform the login.

Main.qml wires this signal to your DataModel. This connection establishes the link from the UI to the Firebase cloud. Replace the current contents of Main.qml with:

import Felgo 3.0
import QtQuick 2.5
import "model"

App {
id: app
licenseKey: "<The Felgo Plugin license key you generated earlier>"

DataModel {
id: dataModel
onLoggedIn: stack.push(shoppingListPage)
}

NavigationStack {
id: stack

LoginPage {
id: loginPage

onLogin: {
if(isRegister) {
// Call the user registration method from our data model,
// which then forwards the request to Google Firebase
dataModel.registerUser(email, password)
} else {
// Similar approach sending a user login request to Firebase.
dataModel.loginUser(email, password)
}
}
}
}

Component {
id: shoppingListPage
MasterPage {
// User navigated back in the UI - send logout request to Firebase
onPopped: dataModel.logoutUser()
}
}
}

In the code snippet above, you see that the App also owns the DataModel item with id “dataModel”. The “App” item connects your app’s components. Here, you establish a direct connection: LoginPage’s “onLogin”-slot -> methods of the DataModel (registerUser / loginUser).

Once the login process completes, the “onLoggedIn” slot within the DataModel pushes the “shoppingListPage” to the navigation stack. Remember: that’s the ID of the MasterPage from the template.

With this approach, navigating back in the Android / iPhone-UI pops the page. This automatically triggers the logout process in Firebase. Your app also returns to the previous page on the navigation stack – the LoginPage.

Test your app! You can already register a new user in Google Firebase and log in:

firebase-app-login

Firebase Realtime Database & Pricing

The Firebase Realtime Database is a NoSQL DB. It’s efficient and low-latency, and especially targeted towards mobile clients.

The Realtime Database stores all data in a JSON tree. Unlike a SQL database, there are no tables and rows. That makes Firebase efficient for simple and rather flat data. It’s the ideal target for many apps, like our shopping list example.

What about pricing? You get charged for bandwidth and storage. The free “Spark Plan” already grants you 100 simultaneous connections, 1 GB of data storage and 10 GB / month data transfer. Upgrades to the “Flame Plan” and the “Blaze Plan” give you even more data allowance. Google has a good comparison table, highlighting the differences between different Firebase plans.

Firebase Database Structure & Live Updates

The following video shows a screen recording of what’s happening behind the scenes:

  1. Left: A new user registers. You see his identifier (the email address). It’s linked to a unique UID (“lC27Aha…”).
  2. Right: Then, the user adds two items to his shopping list: Milk and Apples. Each change made by a client flashes in color – in real-time!

Firebase-Register-New-User-Create-Database-Entry

The hierarchy of the JSON model is as follows:

  1. shoppinglist-vplay: root node of your database. Its name is the project ID you used when creating the Firebase project.
  2. users: added through the authentication part. Keeps data separate for each registered user. The key is the UID of the user. The database itself doesn’t contain the email-address of the user.
  3. shoppinglist-user: root database key, accessible by the individual logged in user. The name is set by the application, as you will do in the next step.
  4. <JSON entries>: in the shopping list scenario, you can use the timestamp as the unique key. The node contains two children:
    1. Timestamp (where you could save the last modification time)
    2. Actual item to buy (string)

This is the default hierarchy, based on customizable rules. But, you have full control to customize every aspect.

Connect to the Firebase Realtime Database

The interface to Firebase is powerful. All connected clients get real-time updates. Plus, it offers full offline-support. When the user goes online again, the changes sync to the cloud.

Felgo includes a single item that works across Android and iOS. Especially for multi-platform scenarios, you’ll love this.

The FirebaseDatabase QML type offers methods to retrieve and update the JSON tree in the Firebase cloud. Callbacks inform you whenever the items changed and when operations complete.

In your app architecture, you set up a data flow from the user interface to the Firebase database in the cloud:

Firebase-Realtime-Database-Add-Data

A “+” button in the navigation bar (1) triggers an input dialog (2). It sends the new shopping item name to the DataModel. The DataModel abstracts the Firebase Realtime database (3). The FirebaseDatabase item from Felgo performs the cloud interaction (4).

Whenever the model data in the cloud changes, your app gets a callback (5). This updates the cached list of shopping items (6).

Firebase Database Configuration & Item Storage

Add the following code snippet to your DataModel:

// Stores a list of all shopping items for the user
property var shoppingItems: ({})

// Name of the root node for the user's shopping items in the Firebase database
readonly property string dbKeyAllShoppingItems: "shoppinglist-user"

FirebaseDatabase {
id: database
config: fbConfig

realtimeUserValueKeys: [dbKeyAllShoppingItems]

// If the last shopping item gets deleted, the database returns null
// the plugin then gives success==false, so don't check the success parameter
onRealtimeUserValueChanged: if(key === dbKeyAllShoppingItems) shoppingItemsLoaded(value)
onFirebaseReady: console.log("db ready")
onWriteCompleted: console.log("write completed")
}

function shoppingItemsLoaded(value) {
// When the last item is deleted, firebase deletes the whole structure, returning null
dataModel.shoppingItems = value || {}
console.log(JSON.stringify(dataModel.shoppingItems))
}

The FirebaseDatabase item (with id database) requires a reference (config) to the generic Firebase connection configuration item with your app keys.

Firebase Realtime Updates

Your app registers for real time updates by adding keys to the realtimeUserValueKeys property.

The realtimeUserValueChanged signal fires every time the monitored keys change. E.g., by another family member sharing your shopping list account. The signal is also emitted when the connection to the database is ready after a successful login. So, it’s the only method we need to retrieve & update the shopping list items!

The shoppingItemsLoaded(value) function then assigns the items to a public property of the DataModel. It also ensures the list never gets null by using an empty array “{}” in case no shopping items have been created so far.

For debugging, you can print the raw JSON data to the console. During development, this helps to see what Firebase transmits to your app. In the video example above, this would be:

{"1529230812085":{"date":1529230812085,"text":"Milk"},"1529230821894":{"date":1529230821894,"text":"Apples"}}

Prepare the Shopping List Page (MasterPage)

The Felgo wizard already created the basic structure of a master list / detail app. You can use this as a base for customizing it to the shopping list scenario.

You need the following functionality:

  • List of shopping items
    • Tap an item to navigate to the detail page. You can edit the item there.
    • Swipe the item to the left to reveal the delete button.
  • “Add” (+) button. Creates a new shopping item.

Add Shopping Items

You assign the keys of the dataModel.shoppingItems array as the model for the list view. The “ListPage” instantiates rows for each item in the model.

The minimal code of the MasterPage:

import Felgo 3.0
import QtQuick 2.5
ListPage {
id: masterPage
title: qsTr("Shopping Items")

model: Object.keys(dataModel.shoppingItems)

signal addNewShoppingItem(string text)

rightBarItem: IconButtonBarItem {
icon: IconType.plus

onClicked: {
InputDialog.inputTextSingleLine(app,
"What to add to the list?", // message text
"Input here", // placeholder text
function(ok, text) {
if(ok) {
masterPage.addNewShoppingItem(text)
}
})
}
}
}

You start with adding shopping items to your Firebase Realtime Database. The “+” button appears in the navigation bar. You achieve this through the rightBarItem, provided by the base Page QML type. Make your life even easier by using the predefined IconType.plus symbol. Thanks to Felgo’s multi-platform support, the button is always placed in the correct screen area for Android and iOS.

To enjoy even more pre-built functionality, use the ListPage QML type as base item of this QML file. “ListPage” derives from the more generic Page type. On top of the generic Page, it includes a full-screen AppListView item. It’ll contain all your shopping items. Plus, it even offers advanced features like fully-animated pull-to-refresh.

When the user taps the “+” button, your app shows a simple single-line text entry dialog (InputDialog).

Store Shopping Items in the Firebase Realtime Database

For a good architecture, you send the user’s new shopping item via a signal to the DataModel. So, define a signal addNewShoppingItem(string text) in the ListPage (with id masterPage). The callback function of the InputDialog then emits the signal. It sends the text entered by the user as parameter.

Now, connect the MasterPage’s signal to the DataModel’s slot. Like before for the login, define it in Main.qml. Extend your previous MasterPage definition in Main.qml:

Component {
id: shoppingListPage
MasterPage {
onAddNewShoppingItem: dataModel.addShoppingItem(text)
// User navigated back in the UI - send logout request to Firebase
onPopped: dataModel.logoutUser()
}
}

Again, the most interesting code is in DataModel. It stores the new shopping item in the Firebase Realtime Database. Add this method to your DataModel:

function addShoppingItem(text) {
var time = new Date().getTime()
var shoppingItem = {
date: time,
text: text
}
console.log("Adding item...")
// Use date milliseconds as unique ID in DB
database.setUserValue(dbKeyAllShoppingItems + "/" + time, shoppingItem, loadingFinished)
}

function loadingFinished() {
console.log("Loading finished")
}

The addShoppingItem function constructs an object “shoppingItem”. The method database.setUserValue() serializes it to JSON. Next, it’s sent to the Firebase database in the cloud. The setUserValue() method has three parameters:

  1. The root node in the user’s JSON tree is “shoppinglist-user”. As the key, you can re-use the time stamp; you can be certain that it’s a unique identifier.
  2. Contains the key/value pairs to store in the database.
  3. Your simple shopping list app doesn’t show that an operation is in progress. You could activate an animation when you send the data. Stop it again when you receive the loadingFinished callback. To get started, log the info to the console.

List Shopping Items in Your App

Your app already adds items to the real time database in the cloud. The last major feature is the UI to show the shopping items!

Back in MasterPage.qml, extend the code of ListPage with a delegate. The delegate instantiates for each individual item in your shopping list.

delegate: SwipeOptionsContainer {
id: container

// modelData == key of shopping item in data model
readonly property var shoppingItem: dataModel.shoppingItems[modelData] || {}

SimpleRow {
width: parent.width

text: container.shoppingItem.text || ""
detailText: new Date(container.shoppingItem.date).toLocaleString() || ""
}
}

The SwipeOptionsContainer QML item supports swipeable list rows in Android and iOS apps. In the next step, you will add the feature to delete the item through the swipe gesture.

Usually, list items have a very simple structure: one or two lines of text, plus an optional image. The Felgo item SimpleRow provides a ready-made layout. The three corresponding properties are: text, detailText and icon.

There’s one simple trick you need to be aware of. How to access the entire individual properties of the currently shown item? The model you assigned to the ListPage only contained the keys. But, the line needs to access the full data of the shopping item! This includes the name and the date.

Where can you get the complete data? It’s stored in the DataModel. Thus, you access it based on the key stored in the list view model. The relevant item data is then available through the readonly property shoppingItem. Its declaration is part of the delegate you inserted a moment ago. This is the relevant line, for reference:

readonly property var shoppingItem: dataModel.shoppingItems[modelData] || {}

Here, you see your app in action:

Firebase-Create-Entry

After the user logs in to the app on the phone, he adds an item with the text “Felgo” to the shopping items list. Thanks to the real-time database features, the item immediately appears in the web view. Google highlights it in green to make you aware of the change.

Even more amazing: real-time changes also work in the other direction. Try deleting a shopping item in the database view on the web. It’ll immediately disappear on the smartphone. No extra code was necessary. In DataModel, Felgo’s FirebaseDatabase item emits a signal every time the remote database changes. In your app, you reload the data based on its new contents.

Delete Items from the NoSQL Firebase Database

Your app already handles real-time updates from the web. Now, the final extension for you to write: let the user delete the shopping items from the phone!

The SwipeOptionsContainer for the ListPage items contains useful out-of-the-box functionality. Like many other advanced apps, users can swipe the item to a side. In your QML, you specify the item to appear. In this case, choose a SwipeButton with red background color and an “X” icon. Now, whenever the user swipes and clicks on the delete button, its onClicked slot executes.

rightOption: SwipeButton {
anchors.fill: parent

backgroundColor: "red"
icon: IconType.remove

// Date is also the unique ID
onClicked: {
container.hideOptions()
masterPage.deleteShoppingItem(container.shoppingItem.date)
}
}

In the onClicked slot, you must inform the real-time database about the deleted item. For this, add a second new signal for the ListPage item in the MasterPage:

signal deleteShoppingItem(real id)

As parameter, your code sends the ID of the item to delete. Remember – we used the creation date as unique ID!

The app must forward the signal to the data model. This architecture keeps the view separated from the model. So, extend the MasterPage component in Main.qml to forward the signal. For reference, this is what the complete component definition looks like now:

Component {
id: shoppingListPage
MasterPage {
onAddNewShoppingItem: dataModel.addShoppingItem(text)
onDeleteShoppingItem: dataModel.deleteShoppingItem(id)
// User navigated back in the UI - send logout request to Firebase
onPopped: dataModel.logoutUser()
}
}

Like adding a shopping item, the signal triggers a JavaScript function in the data model. To stick to the naming scheme, call it deleteShoppingItem(id).

As a final step, jump into DataModel.qml and add the function implementation. It’s only one line and resembles the call to add an item. The only difference: instead of setting the item data as value in the database, you now send null. The result: the item is deleted.

function deleteShoppingItem(id) {
database.setUserValue(dbKeyAllShoppingItems + "/" + id, null, loadingFinished)
}

The animation below shows how deleting item on the phone works. Again, the left side shows the real-time database view of Firebase on the web. Items instantly disappear in the web view when the user has deleted them on the phone.

Firebase-Delete-Entry-VPlay-Qt

Going Further

Your cross-platform shopping list app is powerful:

  • It features an efficient UI to create new items.
  • Delete items through an intuitive swipe gesture.
  • All changes immediately sync to & from the cloud database.
  • Share the login with your family. Everyone will be up-to-date.

For shopping lists, it’s not needed too often. But, for other use cases you might also want to include functionality to edit items. As a bonus, we’ve added the necessary code to the full example on GitHub. Check it out to see how modifying existing items works! Also, the open source example is a great reference, as it includes extra code comments.

By combining the Firebase real-time database with Qt and Felgo, you gain support for user authentication and shared NoSQL-databases with a few lines of code. If you’d also like to store larger files in the cloud, check out the FirebaseStorage QML type.

 

 

 

More Posts Like This

 

qt-machinelearning-tensorflow-Teaser
Machine Learning: Add Image Classification for iOS and Android with Qt and TensorFlow

Qt AR: Why and How to Add Augmented Reality to Your Mobile App
Qt AR: Why and How to Add Augmented Reality to Your Mobile App

vplay-2-17-0-firebase-cloud-storage-downloadable-resources-and-more
Release 2.17.0: Firebase Cloud Storage, Downloadable Resources at Runtime and Native File Access on All Platforms