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.
type Task =
Task
{ name : String
, completed : Bool
}
createTask : String -> Task
completeTask : Task -> Task
type Form a =
Valid a
| Invalid a
| Partial a
validate : (Form a -> Form ()) -> Form a -> Form a
type alias TaskForm =
{ name : String
, validated : Bool
}
validateTaskForm : Form TaskForm -> Form ()
type User =
User
{ name : String
, lastOnline : Posix
}
createUser : String -> Posix -> User
type alias UserForm =
{ name : String
, password : String
, validated : Bool
}
validateUserForm : Form UserForm -> Form ()
type alias TodoPageModel =
{ form :
Form TaskForm
, todo : Array Task
, User : User
}
type alias LoginPageModel =
Form UserForm
type Model =
LoginPage LoginPageModel
| TodoPage TodoPageModel
type LoginPageMsg =
NameEntered String
| PasswordEntered String
| Submited
| GotTime Posix
type TodoPageMsg =
LoggedOut
| TaskAdded String
| TaskCompleted Int
| TaskDeleted
type Msg =
LoginSpecific LoginPageMsg
| TodoSpecific TodoPageMsg
init : () -> Model
updateTodoPage : TodoPageModel -> (TodoPageModel, Cmd TodoPageMsg)
updateLoginPage : LoginPageModel -> (LoginPageModel, Cmd LoginPageMsg)
update : Msg -> (Model, Cmd Msg) -> (Model, Cmd Msg)
viewUserForm : Form UserForm -> Html Msg
viewLoginPage : LoginPageModel -> Html Msg
viewTask : Task -> Html Msg
viewTaskForm : Form TaskForm -> Html Msg
viewTodoPage : TodoPageModel -> Html Msg
view : Model -> Html Msg
subscription : Model -> Sub Msgexposimporting Todo.Page.Login as LoginPage
importing Todo.Page.Todo as TodoPage
type Model =
LoginPage LoginPage.Model
| TodoPage TodoPage.Model
type Msg =
LoginSpecific LoginPage.Msg
| TodoSpecific TodoPage.Msg
init : () -> Model
update : Msg -> (Model, Cmd Msg) -> (Model, Cmd Msg)
view : Model -> Html Msg
subscription : Model -> Sub Msgmodule Todo.Page.Login exposing (Model,Msg,view,update)
importing Todo.Data.Form as Form exposing (Form)
importing Todo.Data.User as User exposing (User,UserForm)
type alias Model =
Form UserForm
type Msg =
NameEntered String
| PasswordEntered String
| Submited
| GotTime Posix
update : Model -> (Model, Cmd Msg)
viewUserForm : Form UserForm -> Html Msg
view : Model -> Html Msgmodule Todo.Page.Login exposing (Model,Msg,view,update)
importing Todo.Data.Task as Task exposing (Task,TaskForm)
importing Todo.Data.User as User exposing (User,UserForm)
type alias Model =
{ form :
Form TaskForm
, todo : Array Task
, User : User
}
type Msg =
LoggedOut
| TaskAdded String
| TaskCompleted Int
| TaskDeleted
update : Model -> (Model, Cmd Msg)
viewTask : Task -> Html Msg
viewTaskForm : Form TaskForm -> Html Msg
view : Model -> Html Msgmodule Todo.Data.Task exposing (Task,create,complete,validate)
importing Todo.Data.Form as Form exposing (Form)
type Task =
Task
{ name : String
, completed : Bool
}
create : String -> Task
complete : Task -> Task
type alias TaskForm =
{ name : String
, validated : Bool
}
validate : Form TaskForm -> Form ()module Todo.Data.Form exposing (Form(..),validate)
type Form a =
Valid a
| Invalid a
| Partial a
validate : (Form a -> Form ()) -> Form a -> Form amodule Todo.Data.User exposing (User,UserForm,create,validate)
importing Todo.Data.Form as Form exposing (Form)
type User =
User
{ name : String
, lastOnline : Posix
}
create : String -> Posix -> User
type alias UserForm =
{ name : String
, password : String
, validated : Bool
}
validate : Form UserForm -> Form ()
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
UserandUserFormintoData/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
📄Article: NoRedInk Style Guide
👥Thread: Code structure/architecture
📄Article: Tour of an Open-Source Elm SPA by Richard Feldman
🎥Video: The life of a file by Evan Czaplicki
Last updated
Was this helpful?