Create an HTML element managed by Elm. The resulting elements are easy to embed in a larger JavaScript projects, and lots of companies that use Elm started with this approach! Try it out on something small. If it works, great, do more! If not, revert, no big deal.
Unlike a sandbox, an element can talk to the outside world in
a couple ways:
Cmd — you can “command” the Elm runtime to do stuff, like HTTP.Sub — you can “subscribe” to event sources, like clock ticks.flags — JavaScript can pass in data when starting the Elm programports — set up a client-server relationship with JavaScriptAs you read the guide you will run into a bunch of examples of element
in this section. You can learn more about flags and ports in the interop
section.
Create an HTML document managed by Elm. This expands upon what element
can do in that view now gives you control over the <title> and <body>.
This data specifies the <title> and all of the nodes that should go in
the <body>. This means you can update the title as your application changes.
Maybe your "single-page app" navigates to a "different page", maybe a calendar
app shows an accurate date in the title, etc.
Note about CSS: This looks similar to an
<html>document, but this is not the place to manage CSS assets. If you want to work with CSS, there are a couple ways:
Packages like
rtfeldman/elm-cssgive all of the features of CSS without any CSS files. You can add all the styles you need in yourviewfunction, and there is no need to worry about class names matching.Compile your Elm code to JavaScript with
elm make --output=elm.jsand then make your own HTML file that loadselm.jsand the CSS file you want. With this approach, it does not matter where the CSS comes from. Write it by hand. Generate it. Whatever you want to do.If you need to change
<link>tags dynamically, you can send messages out a port to do it in JavaScript.The bigger point here is that loading assets involves touching the
<head>as an implementation detail of browsers, but that does not mean it should be the responsibility of theviewfunction in Elm. So we do it differently!
Create an application that manages Url changes.
When the application starts, init gets the initial Url. You can show
different things depending on the Url!
When someone clicks a link, like <a href="/home">Home</a>, it always goes
through onUrlRequest. The resulting message goes to your update function,
giving you a chance to save scroll position or persist data before changing
the URL yourself with pushUrl or load. More info on this in
the UrlRequest docs!
When the URL changes, the new Url goes through onUrlChange. The
resulting message goes to update where you can decide what to show next.
Applications always use the Browser.Navigation module for precise
control over Url changes.
More Info: Here are some example usages of application programs:
These are quite advanced Elm programs, so be sure to go through the guide first to get a solid conceptual foundation before diving in! If you start reading a calculus book from page 314, it might seem confusing. Same here!
All links in an application create a UrlRequest. So
when you click <a href="/home">Home</a>, it does not just navigate! It
notifies onUrlRequest that the user wants to change the Url.
Internal vs ExternalImagine we are browsing https://example.com. An Internal link would be
like:
settings#privacy/homehttps://example.com/home//example.com/homeAll of these links exist under the https://example.com domain. An External
link would be like:
https://elm-lang.org/exampleshttps://other.example.com/homehttp://example.com/homeAnything that changes the domain. Notice that changing the protocol from
https to http is considered a different domain! (And vice versa!)
Having a UrlRequest requires a case in your update like this:
import Browser exposing (..)
import Browser.Navigation as Nav
import Url
type Msg = ClickedLink UrlRequest
update : Msg -> Model -> (Model, Cmd msg)
update msg model =
case msg of
ClickedLink urlRequest ->
case urlRequest of
Internal url ->
( model
, Nav.pushUrl model.key (Url.toString url)
)
External url ->
( model
, Nav.load url
)This is useful because it gives you a chance to customize the behavior in each
case. Maybe on some Internal links you save the scroll position with
Browser.Dom.getViewport so you can restore it
later. Maybe on External links you persist parts of the Model on your
servers before leaving. Whatever you need to do!
Note: Knowing the scroll position is not enough restore it! What if the
browser dimensions change? The scroll position will not correlate with
“what was on screen” anymore. So it may be better to remember
“what was on screen” and recreate the position based on that. For
example, in a Wikipedia article, remember the header that they were looking at
most recently. Browser.Dom.getElement is designed
for figuring that out!
Create a “sandboxed” program that cannot communicate with the outside world.
This is great for learning the basics of The Elm Architecture. You can see sandboxes in action in tho following examples:
Those are nice, but I very highly recommend reading this guide straight through to really learn how Elm works. Understanding the fundamentals actually pays off in this language!