| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
React.Flux.Combinators
Contents
Description
This module contains some useful combinators I have come across as I built a large react-flux application. None of these are required to use React.Flux, they just reduce somewhat the typing needed to create rendering functions.
- clbutton_ :: JSString -> handler -> ReactElementM handler a -> ReactElementM handler a
- cldiv_ :: JSString -> ReactElementM handler a -> ReactElementM handler a
- faIcon_ :: JSString -> ReactElementM handler ()
- foreign_ :: JSString -> [PropertyOrHandler handler] -> ReactElementM handler a -> ReactElementM handler a
- labeledInput_ :: JSString -> ReactElementM handler () -> [PropertyOrHandler handler] -> ReactElementM handler ()
- style :: [(JSString, JSString)] -> PropertyOrHandler handler
- initAjax :: IO ()
- jsonAjax :: (ToJSON body, FromJSON response) => Text -> Text -> [(Text, Text)] -> body -> (Either (Int, Text) response -> IO [SomeStoreAction]) -> IO ()
- data AjaxRequest = AjaxRequest {}
- data AjaxResponse = AjaxResponse {
- respStatus :: Int
- respResponseText :: JSString
- respResponseXHR :: JSVal
- ajax :: AjaxRequest -> (AjaxResponse -> IO [SomeStoreAction]) -> IO ()
Documentation
Arguments
| :: JSString | class names separated by spaces |
| -> handler | the onClick handler for the button |
| -> ReactElementM handler a | the children |
| -> ReactElementM handler a |
cldiv_ :: JSString -> ReactElementM handler a -> ReactElementM handler a Source #
A div_ with the given class name (multiple classes can be separated by spaces). This is useful for defining rows and columns in your CSS framework of choice. I use Pure CSS so I use it something like:
cldiv_ "pure-g" $ do cldiv_ "pure-u-1-3" $ p_ "First Third" cldiv_ "pure-u-1-3" $ p_ "Middle Third" cldiv_ "pure-u-1-3" $ p_ "Last Third"
faIcon_ :: JSString -> ReactElementM handler () Source #
A Font Awesome icon. The given string is prefixed by `fa fa-` and then used as the class for an i element. This allows you to icons such as
faIcon_ "fighter-jet" -- produces <i class="fa fa-fighter-jet"> faIcon_ "refresh fa-spin" -- produces <i class="fa fa-refresh fa-spin">
Arguments
| :: JSString | this should be the name of a property on |
| -> [PropertyOrHandler handler] | properties |
| -> ReactElementM handler a | children |
| -> ReactElementM handler a |
A wrapper around foreignClass that looks up the class on the window. I use it for several third-party react components. For example, with react-modal, assuming `window.ReactModal` contains the definition of the class,
foreign_ "ReactModal" [ "isOpen" @= isModelOpen myProps , callback "onRequestClose" $ dispatch closeModel , "style" @= Aeson.object [ "overlay" @= Aeson.object ["left" $= "50%", "right" $= "50%"]] ] $ do h1_ "Hello, World!" p_ "...."
Here is another example using react-select:
reactSelect_ :: [PropertyOrHandler eventHandler] -> ReactElementM eventHandler () reactSelect_ props = foreign_ "Select" props mempty someView :: ReactView () someView = defineView "some view" $ \() -> reactSelect_ [ "name" $= "form-field-name" , "value" $= "one" , "options" @= [ object [ "value" .= "one", "label" .= "One" ] , object [ "value" .= "two", "label" .= "Two" ] ] , callback "onChange" $ \(i :: String) -> dispatch $ ItemChangedTo i ]
Arguments
| :: JSString | the ID for the input element |
| -> ReactElementM handler () | the label content. This is wrapped in a |
| -> [PropertyOrHandler handler] | the properties to pass to |
| -> ReactElementM handler () |
A label_ and an input_ together. Useful for laying out forms. For example, a stacked Pure CSS Form could be
form_ ["className" $= "pure-form pure-form-stacked"] $ fieldset_ $ do legend_ "A stacked form" labeledInput_ "email" "Email" ["type" $= "email"] labeledInput_ "password" ($(message "password-label" "Your password") []) ["type" $= "password"]
The second labeledInput_ shows an example using React.Flux.Addons.Intl.
style :: [(JSString, JSString)] -> PropertyOrHandler handler Source #
A simple combinator to easily write inline styles on elements.
Ajax
Arguments
| :: (ToJSON body, FromJSON response) | |
| => Text | the method |
| -> Text | the URI |
| -> [(Text, Text)] | the headers. In addition to these headers, |
| -> body | the body |
| -> (Either (Int, Text) response -> IO [SomeStoreAction]) | Once
|
| -> IO () |
Use XMLHttpRequest to send a request with a JSON body, parse the response body as JSON, and then dispatch some actions with the response. This should be used from within the transform function of your store. For example,
data Target = AlienShip | AlienPlanet deriving (Show, Typeable, Generic, ToJSON, FromJSON) data Trajectory = Trajectory { x :: Double, y :: Double, z :: Double, vx :: Double, vy :: Double, vz :: Double } deriving (Show, Typeable, Generic, ToJSON, FromJSON) data UpdatePending = NoUpdatePending | UpdatePending Text | PreviousUpdateHadError Text data MyStore = MyStore { currentTrajectory :: Maybe Trajectory, launchUpdate :: UpdatePending } data MyStoreAction = LaunchTheMissiles Target | MissilesLaunched Trajectory | UnableToLaunchMissiles Text deriving (Typeable, Generic, NFData) instance StoreData MyStore where type StoreAction MyStore = MyStoreAction transform (LaunchTheMissiles t) s = do jsonAjax "PUT" "/launch-the-missiles" [] t $ \case Left (_, msg) -> return [SomeStoreAction myStore $ UnableToLaunchMissiles msg] Right traj -> return [SomeStoreAction myStore $ MissilesLaunched traj] return s { launchUpdate = UpdatePending ("Requesting missle launch against " ++ T.pack (show t)) } transform (MissilesLaunched traj) s = return s { currentTrajectory = Just traj, launchUpdate = NoUpdatePending } transform (UnableToLaunchMissiles err) s = return s { launchUpdate = PreviousUpdateHadError err } myStore :: ReactStore MyStore myStore = mkStore $ MyStore Nothing NoUpdatePendingAnd then in your view, you can render this using something like:
myView :: ReactView () myView = defineControllerView "launch the missles" myStore $ \s () -> do case launchUpdate s of NoUpdatePending -> return () UpdatePending msg -> span_ $ faIcon_ "rocket" <> elemText (T.unpack msg) PreviousUpdateHadErroer err -> span_ $ faIcon_ "exclamation" <> elemText (T.unpack err) clbutton_ ["pure-button button-success"] ([SomeStoreAction myStore $ LaunchTheMissiles AlienShip]) $ do faIcon_ "rocket" "Launch the missles against the alien ship!" p_ $ elemText $ "Current trajectory " ++ show (currentTrajectory s)
data AjaxRequest Source #
The input to an AJAX request built using XMLHttpRequest.
Constructors
| AjaxRequest | |
Instances
| Generic AjaxRequest Source # | |
| type Rep AjaxRequest Source # | |
data AjaxResponse Source #
The response after XMLHttpRequest indicates that the readyState is done.
Constructors
| AjaxResponse | |
Fields
| |
Instances
| Generic AjaxResponse Source # | |
| type Rep AjaxResponse Source # | |
ajax :: AjaxRequest -> (AjaxResponse -> IO [SomeStoreAction]) -> IO () Source #
Use XMLHttpRequest to send a request to the backend. Once the response arrives and the readyState is done, the response will be passed to the given handler and the resulting actions will be executed. Note that ajax returns immedietly and does not wait for the request to finish.