This library wraps elm/core to provide a global context available while building the view.
A context is a global, constant or mostly constant object. It can be used to store those things that you will need almost everywhere in your view but don't change often, or at all.
Examples of things you could want to put in the context:
Example of things that you do not want in the context:
A good test for inclusion is to think of this: does it make sense to completely redraw the user interface when the value changes? In particular, changing anything in the context will force the recalculation of all the lazy nodes.
Define a Context type (it will usually be a type alias);
replace any import Html and any import Html.X with:
import Html.WithContext as Html
import Html.WithContext.Xdon't expose Html or Attribute in the import, but instead define your type aliases:
type Html msg =
Html.Html Context msg
type Attribute msg =
Html.Attribute Context msgpass the context to Html.toHtml;
everything should work as before, but now you can use withContext and withContextAttribute to access your context.
A nice way to do localization is to completely avoid exposing text from Html, and instead defining your custom one like this:
type Language
= En
| It
| Fr
type alias L10N a =
{ en : a
, it : a
, fr : a
}
text : L10N String -> Html { a | language : Language } msg
text { en, it, fr } =
Html.withContext
(\{ language } ->
case language of
En ->
Html.text en
It ->
Html.text it
Fr ->
Html.text fr
)So that you can use it like this: text { en = "Hello", it = "Ciao", fr = "Bonjour" } (you should also probably move all the localized strings into a Localization package).
This has the advantage of keeping a nice API while making it (almost) impossible to have untranslated labels.
Notice how text simply requires a context that includes a language field, so is very generic.
This tecnique can be adapted for image sources, title texts, and anything that needs localization.
Strings with placeholders can be represented as L10N (a -> b -> String) and used by defining an apply : L10N (a -> b) -> a -> L10N b. Beware: different languages can have very different rules on plurals, genders, special cases, ...
If you have a field theme : Theme in your context then you can replace any color constants in your code with Theme -> Color functions, and use them like this:
type Theme
= Light
| Dark
fontColor : Theme -> String
fontColor theme =
case theme of
Light ->
"#333"
Dark ->
"#ddd"
someViewFunction =
div
[ Html.withContextAttribute <| \{theme} -> Attribute.style "color" <| fontColor theme ]
(text "Hello")This also has the advantage that you can "force" a particular theme in places that need it, like the theme picker, by just doing fontColor Light.
elm/htmlHtml msg becomes Html context msg and Attribute msg becomes Attribute context msg,toHtml function,withContext and withContextAttribute functions.You should also have a look at the original README.