Skip to content

Commit c03d0fa

Browse files
authored
Merge pull request #22 from rgrempel/pzingg-v0.18
Further work on updating for Elm 0.18
2 parents 96c67bf + 903296b commit c03d0fa

File tree

22 files changed

+583
-573
lines changed

22 files changed

+583
-573
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
elm-stuff
44
elm.js
55
elm.html
6+
node_modules

README.md

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@
22

33
This is a module for routing single-page-apps in Elm, building on the
44
[`elm-lang/navigation`](http://package.elm-lang.org/packages/elm-lang/navigation/latest)
5-
package. It is the successor to elm-route-hash:
6-
7-
* now compatible with Elm 0.18, and
8-
9-
* no longer limited to working only with the hash (hence the name change).
10-
5+
package.
116

127
## Rationale
138

@@ -32,10 +27,12 @@ such as:
3227
* [Bogdanp/elm-route](http://package.elm-lang.org/packages/Bogdanp/elm-route/latest)
3328
* [etaque/elm-route-parser](http://package.elm-lang.org/packages/etaque/elm-route-parser/latest)
3429
* [poyang/elm-router](http://package.elm-lang.org/packages/poying/elm-router/latest)
30+
* [pzingg/elm-navigation-extra](http://package.elm-lang.org/packages/pzingg/elm-navigation-extra/latest)
3531
* [sporto/erl](http://package.elm-lang.org/packages/sporto/erl/latest)
3632
* [sporto/hop](http://package.elm-lang.org/packages/sporto/hop/latest)
3733

38-
So, what does elm-route-url do differently than the others?
34+
So, what does elm-route-url do differently than the others? First, I'll
35+
address this practically, then philosophically.
3936

4037

4138
### Mapping changes in the app state to a possible location change
@@ -59,6 +56,11 @@ want to ensure is that the URL reflects the final state of your model. (For
5956
instance, consider a module with an `Increment` message and a `Decrement`
6057
message. The URL doesn't care which way you arrived at a particular state).
6158

59+
Furthermore, every state of your model really ought to correspond with some URL.
60+
That is, given some state of your model, there must be something that you'd like
61+
to have appear in the URL. Or, to put it another way, what appears in the URL
62+
really ought to be a function of your state, not the last message you received.
63+
6264
So, elm-route-url asks you to implement a function with a different signature:
6365

6466
```elm
@@ -88,28 +90,45 @@ use elm-route-url, you don't have to.
8890
### Mapping location changes to messages our app can respond to
8991

9092
If you use the official [navigation](http://package.elm-lang.org/packages/elm-lang/navigation/latest)
91-
package in Elm 0.18 directly, the `Navgation.program` differs from the
92-
standard `Html.program` in two ways:
93-
94-
First, you are asked to implement an argument
95-
to `Navigation.program` that converts a `Location` to a message
96-
whenever the URL changes.
97-
98-
Second, the `Navigation.program` takes an init function that
99-
takes a `Location` as an argument. This lets you use the URL on the first frame.
93+
package in Elm 0.18 directly, you react to location changes by providing
94+
an argument to `Navigation.program` which converts a `Location` to a message
95+
your app can deal with. Those messages are then fed into your `update` function
96+
as the `Location` changes.
10097

101-
In elm-route-url, this functionality for both of these is handled by asking
102-
you to implement a function with a different signature:
98+
On the surface, elm-route-url works in a similar manner, except that it
99+
asks you to implement a function which returns a list of messages.
100+
(This is possibly a convenience when you need multiple messages to
101+
react to the URL change, though of course you could also redesign your
102+
app to do multiple things with a single message).
103103

104104
```elm
105105
location2messages : Location -> List Message
106106
```
107107

108-
`location2messages` will be called when the underlying `Navigation.program`
109-
`init` method is invoked, so you don't need to change that in your
110-
program's code. And of course `location2messages` will also be called every
111-
time the location is changed externally (not from a state change that
112-
generated a new location via `delta2url`).
108+
`location2messages` will also be called when your `init` function is invoked,
109+
so you will also get access to the very first `Location`.
110+
111+
So, that is similar to how `Navigation` works. The difference is that
112+
`Navigation` will send you a message even when you programmatically change
113+
the URL. By contrast, elm-route-url only sends you messsages for **external**
114+
changes to the URL -- for instance, the user clicking on a link, opening
115+
a bookmark, or typing in the address bar. You won't get a message when you've
116+
made a change in the URL due to your `delta2url` function, since your state
117+
is already in sync with that URL -- no message is required.
118+
119+
120+
### Philosphically
121+
122+
You can, if you are so inclined, think about those differences in a more
123+
philosophical way. There is a [thread](https://groups.google.com/forum/#!topic/elm-discuss/KacB1VqkVJg/discussion)
124+
on the Elm mailing list where Erik Lott gives an excellent summary.
125+
The question, he says, is whether the address bar should drive the model,
126+
or whether the model should drive the address bar. For more details,
127+
read the thread -- it really is a very good summary.
128+
129+
Another nice discussion of the philosophy behind elm-route-url is in a blog post
130+
by Amitai Burstein, under the heading
131+
[URL Change is not Routing](http://www.gizra.com/content/thinking-choosing-elm/#url-change-is-not-routing)
113132

114133

115134
## API
@@ -127,6 +146,8 @@ moment. How you parse the `Location` (and construct a `UrlChange`) is pretty
127146
much up to you. Now, I have included a `RouteUrl.Builder` module that could
128147
help with those tasks. However, you don't need to use it -- many other
129148
approaches would be possible, and there are links to helpful packages above.
149+
For my own part, I've been using [evancz/url-parser](http://package.elm-lang.org/packages/evancz/url-parser/latest)
150+
recently to implement `location2messages`.
130151

131152
The `RouteHash` module attempts to match the old API of elm-route-hash as
132153
closely as possible. You should be able to re-use your old `delta2update` and

elm-package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
],
99
"exposed-modules": [
1010
"RouteUrl",
11+
"RouteHash",
1112
"RouteUrl.Builder"
1213
],
1314
"dependencies": {

examples/elm-architecture-tutorial/Example1/Counter.elm

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,20 @@ type alias Model =
1515
Int
1616

1717

18-
19-
-- Added from Main.elm
20-
21-
18+
{-| Added from Main.elm
19+
-}
2220
init : Model
2321
init =
2422
0
2523

2624

2725

2826
-- UPDATE
29-
-- We add a Set action for the advanced example, so that we
30-
-- can restore a particular bookmarked state.
3127

3228

29+
{-| We add a Set action for the advanced example, so that we
30+
can restore a particular bookmarked state.
31+
-}
3332
type Action
3433
= Increment
3534
| Decrement
@@ -73,33 +72,30 @@ countStyle =
7372
]
7473

7574

76-
77-
-- We add a separate function to get a title, which the ExampleViewer uses to
78-
-- construct a table of contents. Sometimes, you might have a function of this
79-
-- kind return `Html` instead, depending on where it makes sense to do some of
80-
-- the construction.
81-
82-
75+
{-| We add a separate function to get a title, which the ExampleViewer uses to
76+
construct a table of contents. Sometimes, you might have a function of this
77+
kind return `Html` instead, depending on where it makes sense to do some of
78+
the construction.
79+
-}
8380
title : String
8481
title =
8582
"Counter"
8683

8784

8885

8986
-- Routing (Old API)
90-
-- For delta2update, we provide our state as the value for the URL
9187

9288

89+
{-| For delta2update, we provide our state as the value for the URL.
90+
-}
9391
delta2update : Model -> Model -> Maybe HashUpdate
9492
delta2update previous current =
9593
Just <|
9694
RouteHash.set [ toString current ]
9795

9896

99-
100-
-- For location2action, we generate an action that will restore our state
101-
102-
97+
{-| For location2action, we generate an action that will restore our state.
98+
-}
10399
location2action : List String -> List Action
104100
location2action list =
105101
case list of

examples/elm-architecture-tutorial/Example2/Counter.elm

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@ init count =
3232

3333

3434
-- UPDATE
35-
-- We add a Set action for the advanced example, so that we
36-
-- can restore a particular bookmarked state.
3735

3836

37+
{-| We add a Set action for the advanced example, so that we
38+
can restore a particular bookmarked state.
39+
-}
3940
type Action
4041
= Increment
4142
| Decrement
@@ -81,19 +82,18 @@ countStyle =
8182

8283

8384
-- Routing (Old API)
84-
-- For delta2update, we provide our state as the value for the URL
8585

8686

87+
{-| For delta2update, we provide our state as the value for the URL
88+
-}
8789
delta2update : Model -> Model -> Maybe HashUpdate
8890
delta2update previous current =
8991
Just <|
9092
RouteHash.set [ toString current ]
9193

9294

93-
94-
-- For location2action, we generate an action that will restore our state
95-
96-
95+
{-| For location2action, we generate an action that will restore our state
96+
-}
9797
location2action : List String -> List Action
9898
location2action list =
9999
case list of
@@ -113,18 +113,17 @@ location2action list =
113113

114114

115115
-- Routing (New API)
116-
-- We'll just send back a string
117116

118117

118+
{-| We'll just send back a string
119+
-}
119120
delta2fragment : Model -> Model -> String
120121
delta2fragment previous current =
121122
toString current
122123

123124

124-
125-
-- We'll just take a string
126-
127-
125+
{-| We'll just take a string
126+
-}
128127
fragment2messages : String -> List Action
129128
fragment2messages fragment =
130129
case toInt fragment of

examples/elm-architecture-tutorial/Example2/CounterPair.elm

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,8 @@ type alias Model =
1717
}
1818

1919

20-
21-
-- Rewrote to move initialization from Main.elm
22-
23-
20+
{-| Rewrote to move initialization from Main.elm
21+
-}
2422
init : Model
2523
init =
2624
{ topCounter = Counter.init 0
@@ -68,24 +66,23 @@ view model =
6866
]
6967

7068

71-
72-
-- We add a separate function to get a title, which the ExampleViewer uses to
73-
-- construct a table of contents. Sometimes, you might have a function of this
74-
-- kind return `Html` instead, depending on where it makes sense to do some of
75-
-- the construction.
76-
77-
69+
{-| We add a separate function to get a title, which the ExampleViewer uses to
70+
construct a table of contents. Sometimes, you might have a function of this
71+
kind return `Html` instead, depending on where it makes sense to do some of
72+
the construction.
73+
-}
7874
title : String
7975
title =
8076
"Pair of Counters"
8177

8278

8379

8480
-- Routing (Old API)
85-
-- To encode state in the URL, we'll just delegate & concatenate
86-
-- This will produce partial URLs like /6/7
8781

8882

83+
{-| To encode state in the URL, we'll just delegate & concatenate
84+
This will produce partial URLs like /6/7
85+
-}
8986
delta2update : Model -> Model -> Maybe HashUpdate
9087
delta2update previous current =
9188
-- The implementation is not especially elegant ... perhaps
@@ -116,9 +113,10 @@ location2action list =
116113

117114

118115
-- Routing (New API)
119-
-- We'll put the two counters in the query parameters, just for fun
120116

121117

118+
{-| We'll put the two counters in the query parameters, just for fun
119+
-}
122120
delta2builder : Model -> Model -> Maybe Builder
123121
delta2builder previous current =
124122
builder

examples/elm-architecture-tutorial/Example3/CounterList.elm

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@ init =
3232

3333

3434
-- UPDATE
35-
-- Add an action for the advanced example to set our
36-
-- state from a `List Int`
3735

3836

37+
{-| Add an action for the advanced example to set our
38+
state from a `List Int`
39+
-}
3940
type Action
4041
= Insert
4142
| Remove
@@ -110,27 +111,26 @@ viewCounter ( id, model ) =
110111
Html.map (Modify id) (Counter.view model)
111112

112113

113-
114-
-- We add a separate function to get a title, which the ExampleViewer uses to
115-
-- construct a table of contents. Sometimes, you might have a function of this
116-
-- kind return `Html` instead, depending on where it makes sense to do some of
117-
-- the construction.
118-
119-
114+
{-| We add a separate function to get a title, which the ExampleViewer uses to
115+
construct a table of contents. Sometimes, you might have a function of this
116+
kind return `Html` instead, depending on where it makes sense to do some of
117+
the construction.
118+
-}
120119
title : String
121120
title =
122121
"List of Counters"
123122

124123

125124

126125
-- Routing (Old API)
127-
-- You could do this in a variety of ways. We'll ignore the ID's, and just
128-
-- encode the value of each Counter in the list -- so we'll end up with
129-
-- something like /0/1/5 or whatever. When we recreate that, we won't
130-
-- necessarily have the same IDs, but that doesn't matter for this example.
131-
-- If it mattered, we'd have to do this a different way.
132126

133127

128+
{-| You could do this in a variety of ways. We'll ignore the ID's, and just
129+
encode the value of each Counter in the list -- so we'll end up with
130+
something like /0/1/5 or whatever. When we recreate that, we won't
131+
necessarily have the same IDs, but that doesn't matter for this example.
132+
If it mattered, we'd have to do this a different way.
133+
-}
134134
delta2update : Model -> Model -> Maybe HashUpdate
135135
delta2update previous current =
136136
-- We'll take advantage of the fact that we know that the counter

0 commit comments

Comments
 (0)