The miso-bem
library is to adapt the bem
library for the miso
library.
- to make views having Bem classes more easily
- A view is a
miso
HTML element whoseclass_
attribute is set to a Bem class. - An element view is a view
whose
class_
attribute contains a Bem element. - A block view is an element view
whose
class_
attribute contains a Bem block. - A view generator is a Bem generator into a view.
- A mix view generator is a view generator into a block view.
- A context is a value
having access to the model,
returning either a block view, a mix view generator,
or a
miso
HTML element, and created using a block view maker. - A block view generator is a context returning a mix view generator.
- A view maker is a function from both a
miso
HTML element and its inner views into a view generator. - A block view maker is a view maker into a block view generator.
- A mix view maker is a view maker into a block view.
- An element view generator is a view generator into an element view.
- An element view maker is a view maker into an element view generator.
- All the examples are decorated
according to the
Default value
column from Table 1. - In all the examples the topmost BEM block is the
Root
Bem block. - The context type is the
Reader
type constructor applied to a model type and aView
type constructor applied to an action or a function type whose rightmost type is the latter. - The
miso-bem-example
repository is the working source code of all the examples presented in this document.
- Something
prefixed with the 'Bem' prefix
refers to a
bem
library term.
Follow installing the bem
library
but regarding the miso-bem
library.
- Create a Bem scheme. (?)
- Optionally, create a top-level context binding. (?)
- Run the lop-level context. (?)
Define an element view generator
- obtaining needed data as arguments
- and partially applying an appropriate element view maker function
to both a
miso
HTML element and its inner element views (?) and mix views (?) including the obtained data.
- The element view maker type signatures can be used as type signatures for element view generators.
Follow creating an element view but regarding a mix view generator and a mix view maker function.
src/View/Search.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
module View.Search where
import Bem.Scheme
import Bem.Miso.View.Html
import Bem.Miso.View.Mk.Mk
import Miso
import Bem.Init
import Bem.Miso.Utl.Utl
search :: BlkNoModsElem' ()
search
=
_blkNoModsElem mks (NonVoidHtmlElem section_)
( []
, ([ blkElem (VoidHtmlElem input_)
[placeholder_ "Text to search"]
TextInput
[TextInput_Dark]
Search
Search_TextInput
[SearchTextInput_Size Big]
, blkElem (VoidHtmlElem input_)
[type_ "button", value_ "Search"]
Btn
[Btn_Dark]
Search
Search_Btn
[SearchBtn_Size Big]
]
)
)
- The mix view maker type signatures can be used as type signatures for mix view generators.
- If an element view generator is also needed to have a BEM block, create an equivalent mix view generator using a mix view maker instead.
- If an element view generator is too complex or used in multiple places, then it should be a top-level binding.
Define a context,
- obtaining needed data
- and returning the block view generator
partially applying an appropriate block view maker
to both a
miso
HTML element including its inner views and the obtained data,
from it.
src/View/Header.hs
{-# LANGUAGE OverloadedStrings #-}
module View.Header where
import Bem.Scheme
import View.Search
import Bem.Miso.View.Html
import Control.Monad.Reader
import Miso
import Miso.String
import Bem.Miso.Utl.Utl
import Bem.Init
mkHeader :: MkBlkNoModsElem' () MisoString
mkHeader = do
userName <- ask
_mkBlkNoModsElem mks (NonVoidHtmlElem header_)
( []
, [ noModsBlkNoModsElem (NonVoidHtmlElem span_)
([], [text "Logo"])
Logo
Root
Root_Logo
, span_ [] [text userName]
, search Search [Search_Dark] Header Header_Search
]
)
- The block view generator type aliases can be used as type signatures for block view generators.
- The partial view makers can be used in place of the regular ones to omit corresponding needless modifiers.
Follow configuring the Bem class generators
but regarding the miso-bem
init
function
and Mks
record.
Follow creating an element view using the default decorations but regarding a configured (?) element view maker field-function.
Follow creating an element view using the default decorations but regarding a mix view generator and a configured (?) mix view maker field-function.
src/View/Search.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
module View.Search where
import Bem.Scheme
import Bem.Miso.View.Html
import Bem.Miso.View.Mk.Mk
import Miso
import Bem.Init
import Bem.Miso.Utl.Utl
search :: BlkNoModsElem' ()
search
=
_blkNoModsElem mks (NonVoidHtmlElem section_)
( []
, ([ blkElem (VoidHtmlElem input_)
[placeholder_ "Text to search"]
TextInput
[TextInput_Dark]
Search
Search_TextInput
[SearchTextInput_Size Big]
, blkElem (VoidHtmlElem input_)
[type_ "button", value_ "Search"]
Btn
[Btn_Dark]
Search
Search_Btn
[SearchBtn_Size Big]
]
)
)
Follow creating a block view using the default decorations but regarding a configured block view maker field-function.
src/View/Header.hs
{-# LANGUAGE OverloadedStrings #-}
module View.Header where
import Bem.Scheme
import View.Search
import Bem.Miso.View.Html
import Control.Monad.Reader
import Miso
import Miso.String
import Bem.Miso.Utl.Utl
import Bem.Init
mkHeader :: MkBlkNoModsElem' () MisoString
mkHeader = do
userName <- ask
_mkBlkNoModsElem mks (NonVoidHtmlElem header_)
( []
, [ noModsBlkNoModsElem (NonVoidHtmlElem span_)
([], [text "Logo"])
Logo
Root
Root_Logo
, span_ [] [text userName]
, search Search [Search_Dark] Header Header_Search
]
)
- In order that a
miso
HTML element can be passed into a view maker, wrap it into theHtmlElem
GADT, namely,- a non-void one into the
NonVoidHtmlElem
data constructor - and a void one into the
VoidHtmlElem
data constructor.
- a non-void one into the
- In order that the
Mks
field-functions using custom decorations can be used, they must be configured. (?)
- The partial view makers can be used in place of the full ones to omit corresponding needless modifiers.
- Bind a name to a context
returning either a
miso
HTML element or a block view. - Include each top-level block view into the
miso
HTML element that it returns. (?) - Set the resulting
miso
HTML element as a value of theview
field of theApp
record.
src/View/Root.hs
{-# LANGUAGE OverloadedStrings #-}
module View.Root where
import Bem.Scheme
import View.Header
import Bem.Miso.Utl.Utl
import Miso
import Miso.String
mkRoot :: MkSingleton' () MisoString
mkRoot = do
BlkNoModsElem header <- mkHeader
return
$ div_
[class_ "Root"]
[header Header [Header_Dark] Root Root_Header]
- The topmost BEM block should be invisible HTML element.
- If a context is defined as a top-level binding,
then the
MkSingleton
type constructor applied to the model and the action can be used as a type signature for it. - If a top-level context returns a
miso
HTML element having a topmost BEM block, then global styles can be set on the topmost BEM block. - In order that the BEM rules are obeyed, the topmost BEM block should be used as a parent for top-level BEM elements
- Run an included block view generator in an including context
to obtain the wrapped block view generator using
do
notation. - Unwrap the obtained wrapped block view generator using pattern matching over an appropriate wrapper data constructor.
- Bind a name to the unwrapped block view generator inside the mattern match.
- Follow
- Bem classes generating using the default decorations
- or Bem classes generating using custom decorations but regarding the bound block view generator to obtain a block view.
- Pass the obtained block view into the block view maker used to create the returned view block generator.
Follow including block view but from the fourth step and regarding an element view generator.
Follow including element view but regarding mix view generators.
- Run a lop-level context applying the
runReader
function to it to obtain amiso
HTML element. - Set the obtained
miso
HTML element as a value of theview
field of theApp
record.
src/Main.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
import View.Root
import Control.Monad.Reader
import Language.Javascript.JSaddle.Warp
import Miso
main :: IO ()
main
=
runApp
$ startApp
App { events = defaultEvents
, initialAction = ()
, logLevel = Off
, model = "Monadosquito"
, mountPoint = Nothing
, subs = []
, update = \_ mdl -> noEff mdl
, view = runReader mkRoot
}
#ifndef __GHCJS__
runApp :: JSM () -> IO ()
runApp = debug 8000
#else
runApp :: IO () -> IO ()
runApp = id
#endif
- The example runs a local HTTP server
serving the following HTML code on the
8000
port:
result.html
<html>
<head>
</head>
<body>
<script src="/jsaddle.js"></script>
<div class="Root">
<header class="header header_dark root__header">
<span class="logo root__logo">Logo</span>
<span>Monadosquito</span>
<section class="search search_dark header__search">
<input class="text-input text-input_dark search__text-input search__text-input_size_big" placeholder="Text to search">
<input class="btn btn_dark search__btn search__btn_size_big" type="button" value="Search">
</section>
</header>
</div>
</body>
</html>
- If a name is bound to a top-level context, then use it as a top-level context by its name.
This library can be contributed into
the way that the bem
library can.
This library follows the convention
followed by the bem
library.
- cfg
- utl
- view