Fifthtry

Hello Elm

In realm, we store all our frontend code in a folder named, “frontend”. Lets create it:

mkdir frontend

elm.json

Elm expects an elm package to contain an elm.json, here is the one from fifthtry (content of frontend/elm.json):

{
    "type": "application",
    "source-directories": [
        "../../realm/frontend/",
        "./"
    ],
    "elm-version": "0.19.0",
    "dependencies": {
        "direct": {
            "elm/browser": "1.0.1",
            "elm/core": "1.0.2",
            "elm/html": "1.0.0",
            "elm/http": "2.0.0",
            "elm/json": "1.1.3",
            "elm/svg": "1.0.0",
            "elm/time": "1.0.0",
            "elm/url": "1.0.0",
            "hecrj/html-parser": "2.3.4",
            "krisajenkins/remotedata": "6.0.1",
            "mdgriffith/elm-style-animation": "4.0.0",
            "mdgriffith/elm-ui": "1.1.5",
            "rtfeldman/elm-hex": "1.0.0",
            "sporto/time-distance": "1.0.1"
        },
        "indirect": {
            "elm/bytes": "1.0.8",
            "elm/file": "1.0.5",
            "elm/parser": "1.1.0",
            "elm/virtual-dom": "1.0.2"
        }
    },
    "test-dependencies": {
        "direct": {},
        "indirect": {}
    }
}

You probably do not need elm/svg sporto/time-distance and few others, but you can let them be, as they do not cost anything unless you use them.

Realm.App

Lets first look at the type “Realm.App”:

import Realm as R
import Json.Decode as JD
import Browser as B


type alias App config model msg =
    { config : JD.Decoder config
    , init : R.In -> config -> ( model, Cmd (R.Msg msg) )
    , update : R.In -> msg -> model -> ( model, Cmd (R.Msg msg) )
    , subscriptions : R.In -> model -> Sub (R.Msg msg)
    , document : R.In -> model -> B.Document (R.Msg msg)
    }

If you know elm, this is very close to Browser.document:

document :
    { init : flags -> ( model, Cmd msg )
    , view : model -> Document msg
    , update : msg -> model -> ( model, Cmd msg )
    , subscriptions : model -> Sub msg
    }
    -> Program flags model msg

If the above looks unfamiliar, refer “web apps” section of Elm guide.

Lets focus on what’s Realm.App bringing to the table beyond what’s in Browser.document.

Config

The first thing to notice is the config : JD.Decode config.

Config is what was sent from the server, it represents the data in the Page struct we created in our route.

The data is sent from backend as JSON, so we have to proved a Json.Decoder, which is our first argument.

init

init of Browser.document is flags -> ( model, Cmd msg ), where flags represents the data sent by javascript when the Elm app was getting initialised.

In realm, Realm.js initialises your elm app, and there is no flags. What we have instead is: R.In -> config -> ( model, Cmd (R.Msg msg) ), where Realm.In tells you a bit about the environment, and config is data sent from server, our config.

A Note on Realm.Msg msg

In Browser.document, you defined your own message type, msg, and is used in init, update, etc. In Realm we have a type Realm.Msg msg, which is the return type for init, update etc.

This makes it easy for you to return messages defined by Realm to opt in some features provided in Realm as we will see later.

update, document and subscriptions

These methods in Realm.App resemble Browser.document, they just get an extra R.In parameter.

Our First Elm Page: Pages.Index

It is also recommended that each elm module responsible for a route be named inside an elm “package” named “Pages”.

mkdir frontend/Pages

Lets use this to create our Index page, frontend/Pages/Index.elm:

module Pages.Index exposing (Config, app, main)

import Browser as B
import Element as E
import Json.Decode as JD
import Realm as R


type alias Config =
    { hello : String 
    }


config : JD.Decoder Config
config = 
    JD.map Config 
        (JD.field "hello" JD.string)


view : Config -> E.Element (R.Msg ())
view c =
    E.text ("Hello Elm, data from server: " ++ c.hello)


app : R.App Config Config ()
app =
    R.App config R.init0 R.update0 R.sub0 (always view >> R.document)


main =
    R.app app

In realm 0.2, we will auto generate the Config type and config decoder, based on Rust struct.

Building elm.js

We are going to use elm make to build our elm.js:

cd frontend
elm make Pages/Index.elm --output=elm.js
cd -

We will be building a sophisticated builder using doit later on.

We have to now learn how to serve static files using our rust server.

Table Of Content

What is Realm?

A Bit On Motivation

Routing is Hard

What does Realm do?

Backend Data And Type Safety

Tutorial

Quick Start Realm Tutorial

In Depth Tutorial (not ready)

Nix
Shell
Doit
Hello Rust
Hello Elm
Hello Static Files
Hello Server Side Rendering
Pre-Commit Hooks

Routing, Request And Response

Frontend, Data, Navigation, And APIs

How To Guides

File Upload

Backend: S3 File Upload
Authenticated File Serving
Frontend: Uploading Files From Elm

How to use storybook?

How to implement “loading..”?

Docs

Realm.In

Realm.Storybook.Story

realm::In

realm::Context

realm::Result

realm.magicSlice

realm::RequestConfig

Environment Variables

Internals - Only for Realm Developers, not Users

“Realm DATA”
iFrame Controller
Shutdown Routine
Testing Internals

Change Log

Get Realm Starter Working

Transparent Offline Feature

How to make http requests in Realm?

Development

Tutorial: ToDo App

Realm Testing

Enhance Realm Starter

Double Load Issue

Deploy To Heroku Button

End failure

Realm-Starter Github Template

Proposal: Tracker And Visit

Proposal: Activity Store

Proposal: Bundling

Proposal: Retry On Network Error

Storybook: Editable JSON

Storybook: Notes

Storybook: Reference

Backlog

Readings

Change Log

How to Publish

Testing

Code Snippets

Skip rustfmt For Some Section

Close Modal Dialog When Clicked Outside

Ignoring Lints In Python

Ignoring Lints (clippy and rustc warnings) In Rust

Handle DateTime in Rust & Elm

Handle CiText value read in Rust

Transport Enum Type to and fro Rust/Elm through JSON