How to structure an Elm project?
The answer to this question can be found in the Beginning Elm book. This question will therefore be removed at some time in the future.
Do not overuse: Files are allowed to get quite big without needing to split them.
Problem
Solution
Todo.elm
1
type Task =
2
Task
3
{ name : String
4
, completed : Bool
5
}
6
​
7
createTask : String -> Task
8
​
9
completeTask : Task -> Task
10
​
11
type Form a =
12
Valid a
13
| Invalid a
14
| Partial a
15
​
16
validate : (Form a -> Form ()) -> Form a -> Form a
17
​
18
type alias TaskForm =
19
{ name : String
20
, validated : Bool
21
}
22
​
23
validateTaskForm : Form TaskForm -> Form ()
24
​
25
type User =
26
User
27
{ name : String
28
, lastOnline : Posix
29
}
30
​
31
createUser : String -> Posix -> User
32
​
33
type alias UserForm =
34
{ name : String
35
, password : String
36
, validated : Bool
37
}
38
​
39
validateUserForm : Form UserForm -> Form ()
40
​
41
type alias TodoPageModel =
42
{ form :
43
Form TaskForm
44
, todo : Array Task
45
, User : User
46
}
47
​
48
type alias LoginPageModel =
49
Form UserForm
50
​
51
type Model =
52
LoginPage LoginPageModel
53
| TodoPage TodoPageModel
54
type LoginPageMsg =
55
NameEntered String
56
| PasswordEntered String
57
| Submited
58
| GotTime Posix
59
​
60
type TodoPageMsg =
61
LoggedOut
62
| TaskAdded String
63
| TaskCompleted Int
64
| TaskDeleted
65
​
66
type Msg =
67
LoginSpecific LoginPageMsg
68
| TodoSpecific TodoPageMsg
69
​
70
init : () -> Model
71
​
72
updateTodoPage : TodoPageModel -> (TodoPageModel, Cmd TodoPageMsg)
73
​
74
updateLoginPage : LoginPageModel -> (LoginPageModel, Cmd LoginPageMsg)
75
​
76
update : Msg -> (Model, Cmd Msg) -> (Model, Cmd Msg)
77
​
78
viewUserForm : Form UserForm -> Html Msg
79
​
80
viewLoginPage : LoginPageModel -> Html Msg
81
​
82
viewTask : Task -> Html Msg
83
​
84
viewTaskForm : Form TaskForm -> Html Msg
85
​
86
viewTodoPage : TodoPageModel -> Html Msg
87
​
88
view : Model -> Html Msg
89
​
90
subscription : Model -> Sub Msgexpos
Copied!
Main.elm
1
importing Todo.Page.Login as LoginPage
2
importing Todo.Page.Todo as TodoPage
3
​
4
type Model =
5
LoginPage LoginPage.Model
6
| TodoPage TodoPage.Model
7
​
8
type Msg =
9
LoginSpecific LoginPage.Msg
10
| TodoSpecific TodoPage.Msg
11
​
12
init : () -> Model
13
​
14
update : Msg -> (Model, Cmd Msg) -> (Model, Cmd Msg)
15
​
16
view : Model -> Html Msg
17
​
18
subscription : Model -> Sub Msg
Copied!
Page/Login.elm
1
module Todo.Page.Login exposing (Model,Msg,view,update)
2
​
3
importing Todo.Data.Form as Form exposing (Form)
4
importing Todo.Data.User as User exposing (User,UserForm)
5
​
6
type alias Model =
7
Form UserForm
8
9
type Msg =
10
NameEntered String
11
| PasswordEntered String
12
| Submited
13
| GotTime Posix
14
​
15
update : Model -> (Model, Cmd Msg)
16
​
17
viewUserForm : Form UserForm -> Html Msg
18
​
19
view : Model -> Html Msg
Copied!
Page/Todo.elm
1
module Todo.Page.Login exposing (Model,Msg,view,update)
2
​
3
importing Todo.Data.Task as Task exposing (Task,TaskForm)
4
importing Todo.Data.User as User exposing (User,UserForm)
5
​
6
type alias Model =
7
{ form :
8
Form TaskForm
9
, todo : Array Task
10
, User : User
11
}
12
​
13
type Msg =
14
LoggedOut
15
| TaskAdded String
16
| TaskCompleted Int
17
| TaskDeleted
18
​
19
update : Model -> (Model, Cmd Msg)
20
​
21
viewTask : Task -> Html Msg
22
​
23
viewTaskForm : Form TaskForm -> Html Msg
24
​
25
view : Model -> Html Msg
Copied!
Data/Task.elm
1
module Todo.Data.Task exposing (Task,create,complete,validate)
2
​
3
importing Todo.Data.Form as Form exposing (Form)
4
​
5
type Task =
6
​
7
Task
8
{ name : String
9
, completed : Bool
10
}
11
​
12
create : String -> Task
13
​
14
complete : Task -> Task
15
​
16
type alias TaskForm =
17
{ name : String
18
, validated : Bool
19
}
20
​
21
validate : Form TaskForm -> Form ()
Copied!
Data/Form.elm
1
module Todo.Data.Form exposing (Form(..),validate)
2
​
3
type Form a =
4
Valid a
5
| Invalid a
6
| Partial a
7
​
8
validate : (Form a -> Form ()) -> Form a -> Form a
Copied!
Data/User.elm
1
module Todo.Data.User exposing (User,UserForm,create,validate)
2
​
3
importing Todo.Data.Form as Form exposing (Form)
4
​
5
type User =
6
User
7
{ name : String
8
, lastOnline : Posix
9
}
10
​
11
create : String -> Posix -> User
12
​
13
type alias UserForm =
14
{ name : String
15
, password : String
16
, validated : Bool
17
}
18
​
19
validate : Form UserForm -> Form ()
Copied!

Question

How should I structure my Elm project?

Answer

Use the following file structure:
  • Main.elm - Contains the main code
  • Data.elm - Contains utility functions for types (like constants)
    • Data/.. - Contains types. Group them logically, for example User and UserForm into Data/User.elm.
  • View.elm - Contains utility functions for views (like view specific constants and very general function.)
    • View/.. - Contains different Views. Sometimes a type has different views. A login page might have a special view for a wrong login.
  • Page.elm - Contains utility functions for pages. For page-transitions its handy to store the different models in here.
    • Page/.. - Contains a Model/View/Update for every page.
  • .. - in the same style you can add your project specific folders like a separate folder for validation.

Further reading