5.20231.904
5.20231.904

Firestore Overview

Wijmo's Firestore class uses the Firestore REST API to allow you to load, view, and edit Firestore databases. Though the Firestore class is fast and light, it does not provide any of the advanced features provided by the Firestore web client library, such as off-line caching and real time updates. If you have determined that your application will require those features, or if you're already committed to using the Firestore web client library, consider using the Snapshot class instead of the Firestore class.

Creating the Firestore Database

First, you'll need to create your Firestore database. The steps to do so are as follows:

  1. Go to the Firebase console
  2. Create a new project (or select an existing one)
  3. Click the database button
  4. Add a Firestore database
  5. Use the UI to configure the database

There are many tutorials and videos that cover Firestore database setup in detail, including:

After creating the database and populating it with data, you'll need to generate an API key to allow your application to connect to the database. This can be done through the Google API Console.

Access Firestore from the App

Now that the database has been created and we've created our API key, we can import the Firestore class and use that to connect to the database.

First, we'll need to import the Firestore class:

import { Firestore } from '@grapecity/wijmo.cloud';

Then, we'll create a Firestore object connected to our database:

const API_Key = 'AIzaSyCvuXEzP57I5CQ9ifZDG2_K8M3nDa1LOPE';
const PROJECT_ID = 'test-9c0be';
let fsNWind = new Firestore(PROJECT_ID, API_KEY, {
    collections: ['Products', 'Categories', 'Suppliers']
});

Finally, we'll add a ComboBox to allow users to see and select product categories, a FlexGrid to display the data of the categories that the user selected, and a FlexChart to show the unit price for the products in the database.

ComboBox

let categoryCombo = new ComboBox('#categoryCombo', {
    placeholder: '(All Categories)',
    isRequired: false,
    displayMemberPath: 'CategoryName',
    itemsSource: fsNWind.getCollection('Categories'),
    selectedIndexChanged: (s, e) => {
        let cat = s.selectedItem;
        fsNWind.getSheet('Products').filter = (item => {
            return cat == null || cat.CategoryID == item.CategoryID;
        });
    }
});

FlexGrid

let supplierMap = new DataMap(fsNWind.getCollection('Suppliers'), 'SupplierID', 'CompanyName');
let productGrid = new FlexGrid('#productGrid', {
    ...gridOptions,
    autoGenerateColumns: false,
    columns: [
        { binding: 'ProductName', header: 'Product Name' },
        { binding: 'UnitPrice', header: 'Unit Price', format: 'n2' },
        { binding: 'QuantityPerUnit', header: 'Quantity Per Unit' },
        { binding: 'SupplierID', header: 'Supplier', dataMap: supplierMap },
        { binding: 'UnitsInStock', header: 'In Stock', format: 'n0' },
        { binding: 'UnitsOnOrder', header: 'On Order', format: 'n0' },
    ],
    itemsSource: fsNWind.getCollection('Products')
});

FlexChart

let productChart = new FlexChart('#productChart', {
    chartType: 'Bar',
    axisX: { majorGrid: true, axisLine: false },
    axisY: { majorGrid: false, axisLine: false, reversed: true },
    legend: { position: 'Bottom' },
    bindingX: 'ProductName',
    series: [
        { binding: 'UnitPrice', name: 'Product Unit Prices (US$)' }
    ],
    itemsSource: fsNWind.getCollection('Products')
});

And now the controls have been connected to the Firestore database. This is all standard Wijmo code, the data could have been loaded from any data source. In this case, we used the Firestore object to load the data into the controls.

Committing Changes

Whenever a user changes, adds or removes and item, the Firestore class commits changes to the data store immediately. This default behavior minimizes the chances of data loss.

If you prefer to defer the commit operations and apply them on-demand, set the Collection's deferCommits property to true and call the commitChanges (or cancelChanges) methods whenever you want.

For example, the the code below shows how you can use the hasPendingChanges property to determine whether the Collection has pending changes and the commitChanges and cancelChanges methods to apply or cancel them:

// get the collection and configure it  
let collection = fs.getCollection('restaurants');  
collection.deferCommits = true;  

// commit/cancel changes buttons  
let btnCommit = document.getElementById('btn-commit') as HTMLButtonElement,  
    btnCancel = document.getElementById('btn-cancel') as HTMLButtonElement;  

// commit or cancel pending changes  
btnCommit.addEventListener('click', () => collection.commitChanges());  
btnCancel.addEventListener('click', () => collection.cancelChanges());  

// enable buttons when there are pending changes  
collection.hasPendingChangesChanged.addHandler((s, e) => {  
    btnCommit.disabled = btnCancel.disabled = !collection.hasPendingChanges;  
});