Connect Firebase to an Elm app and read/write data to db
In this Answer, we’ll establish a connection between Firebase and our Elm application to facilitate data retrieval and modification from the database. Firebase is a popular Backend-as-a-Service (BaaS) platform provided by Google that offers multiple application development and cloud computing services. Conversely, Elm is a functional language that compiles to JS. In Elm, we facilitate ports that allow communication with the JS code, enabling us to perform database read and write operations.
Connecting our Elm application with the Firebase app involves several steps.
Step 1: Creating a real-time database in Firebase
We can create the real-time database by following the instructions provided in this Firebase as simple database to React app. Once the real-time database is created, create a key-value pair, which we will receive and modify in our Elm application.
Once the Firebase project is set up, we’ll copy the configuration details essential for our connection to our database. The configuration details will be presented in the following format:
const firebaseConfig = {apiKey: "YOUR_API_KEY",authDomain: "YOUR_AUTH_DOMAIN",databaseURL: "YOUR_DATABASE_URL",projectId: "YOUR_PROJECT_ID",storageBucket: "YOUR_STORAGE_BUCKET",messagingSenderId: "YOUR_MESSAGING_SENDER_ID",appId: "YOUR_APP_ID",measurementId: "YOUR_MEASUREMENT_ID"};
You can easily customize these values to match the configuration of your specific project.
Step 2: Firebase Read and write
To communicate with firebase.js file and Elm application, we’ll use ports. We’ll define the ports for data exchange within our Main.elm file.
port firebaseWrite : String -> Cmd msgport firebaseRead : (String -> msg) -> Sub msg
These ports will allow our Elm application to send and receive data from JS.
Line 1:
firebaseWriteport accepts a string as an input and returns aCmd msg(command message).Line 2:
firebaseReadport accepts a string as an input and returns aSub msg(subscription to message).
To ensure data transmission between the two components, we'll incorporate these subscriptions into our firebase.js file.
app.ports.firebaseWrite.subscribe(function(data) {firebase.database().ref("score").set(data);});firebase.database().ref("score").on("value", function(snapshot) {app.ports.firebaseRead.send(snapshot.val());});
Lines 1–3:
firebaseWritewill listen for incoming data on this port. Whenever data is received on the port,firebase.database().ref("score").set(data);function will be invoked. This function will write the incoming data to thescorekey in our database.Lines 5–7:
firebaseReadport listens for thevalueevent, and whenever the event occurs, thefirebaseRead.send(snapshot.val());will be triggered andsnapshot.val()will retrieve the current value on the real-time database and send it to thefirebaseReadport.
Step 3: Creating an Elm application
To build an Elm application, we’ll define the Model, View, Update and Subscriptions in our Elm file.
Define the Model function
This Model defines the current state of our application. In our application, we will use an integer variable to represent the score, which we intend to read from and write to the database.
type alias Model ={ count : Maybe Int}
The count holds our our integer value which we will initialize to 1.
Define the View function
This view is responsible for defining the content to display in our html file, and that data is rendered from the view to our html file.
-- Viewview : Model -> Html Msgview model =case model.count ofJust n ->Html.text <|"The score is " ++ String.fromInt n ++ "."Nothing ->Html.text "Loading score ..."
The above view essentially generates the visual representation for our application from our Model state.
Line 3: It takes the
Modelas an input and returnsHtml Msg. This message will be rendered to our Elm application.Lines 5–8: The view function renders data based on two conditions: if our
countvalue has some integer stored in it, then display the score.Lines 10–11: Otherwise, if no integer value is present, it will execute the
Nothingcase.
Define the Subscription function
To establish a subscription to the onClick browser event in our elm application, we'll create a subscription function that listens for this event and triggers updates to the Model.
-- Subscriptionssubscriptions : Model -> Sub Msgsubscriptions model =Sub.batch[ Browser.Events.onClick (Json.Decode.succeed Click), firebaseRead ReceiveValue]
Line 3: The function accepts
Modelas an input and returns aSub Msg(subscription to Messages).Lines 6–8: Whenever an on-click event occurs,
firebaseReadfunction will be invoked.
Define the Update function
The update function plays an important role in modifying the Model and generating command messages based on user interactions. The update function takes Model as an input and returns a tuple containing the modified Model and a command message.
-- Updateupdate : Msg -> Model -> (Model, Cmd Msg)update msg model =case msg ofClick ->case model.count ofJust n ->( model, firebaseWrite (String.fromInt (n + 1)))Nothing ->( model, Cmd.none)
Lines 3–4: The
updatefunction is updating the model based on the user’s click.Lines 6–11: Whenever a user clicks on the web page, it checks the
countvalue. If there is some value stored incountthen increment it, and thefirebaseWritefunction is called, which overwrites this value on our real-time database.Lines 13–16: Otherwise, just return the same model and do not run any command.
ReceiveValue value ->case String.toInt value ofJust n ->( { model | count = Just n }, Cmd.none)Nothing ->( model, Cmd.none)
Lines 1–2: When a value of the
ReceiveValuetype is received, we perform a conversion operation fromStringtoInt.Lines 3–6: if conversion is successful, we proceed to update the count within our
Model.Lines 7–9: Otherwise, if the conversion operation encounters an error, no action is taken.
Code example
Now, let’s look at the example where we are integrating Firebase and our Elm application. Make sure to replace the values in firebaseConfig according to your Firebase project configurations.
app.ports.firebaseWrite.subscribe(function(data) {
firebase.database().ref("score").set(data);
});
firebase.database().ref("score").on("value", function(snapshot) {
app.ports.firebaseRead.send(snapshot.val());
});After executing the code, we get the output, as shown in the illustration below:
By simply clicking anywhere on the screen the score variable is updated on Firebase, and the change is shown on our screen.
Conclusion
In summary, we connected with the Firebase real-time database using its configuration details. We retrieved a value by providing a specific location score in the database, storing it in the Elm count variable, and displaying this value on our browser screen. A single click on the screen updates the variable and also writes the new value to the real-time database.
Free Resources