Created
October 29, 2018 16:46
-
-
Save dariooddenino/eb0fc7fd863ae37d8ca9962b7ea824dc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Components.Form.Search where | |
import Prelude | |
import Bulma as B | |
import Component.Utils.Debounced (DebounceTrigger, cancelDebounceTrigger, debouncedEventSource, runDebounceTrigger) | |
import Data.Foldable (for_) | |
import Data.Maybe (Maybe(..)) | |
import Data.String (length, null) | |
import Effect.Aff (Aff, Milliseconds) | |
import Halogen as H | |
import Halogen.HTML as HH | |
import Halogen.HTML.Events as HE | |
import Halogen.HTML.Properties as HP | |
import Record as Record | |
data Query a | |
= Initialize a | |
| Finalize a | |
| Search String a | |
| SendSearch a | |
| Receive Input a | |
type Input = { minLength :: Int | |
, debounceTime :: Milliseconds | |
, loading :: Boolean | |
} | |
type State = { minLength :: Int | |
, debounceTime :: Milliseconds | |
, search :: Maybe String | |
, loading :: Boolean | |
, searchTrigger :: Maybe (DebounceTrigger Query Aff) | |
} | |
data Message = New (Maybe String) | |
component :: H.Component HH.HTML Query Input Message Aff | |
component = | |
H.lifecycleComponent | |
{ initialState: Record.merge { searchTrigger: Nothing | |
, search: Nothing | |
} | |
, render | |
, eval | |
, receiver: const Nothing | |
, initializer: Just (H.action Initialize) | |
, finalizer: Just (H.action Finalize) | |
} | |
where | |
render :: State -> H.ComponentHTML Query | |
render s = | |
HH.div | |
[ HP.class_ B.field ] | |
[ HH.div | |
[ HP.classes [ B.control, B.hasIconsRight ] ] | |
[ HH.input [ HP.class_ B.input | |
, HP.type_ HP.InputText | |
, HP.placeholder "Search..." | |
, HE.onValueInput (HE.input $ Search) | |
, HP.disabled s.loading | |
] | |
, HH.span | |
[ HP.classes [ B.icon, B.isSmall, B.isRight ] ] | |
[ HH.i [ HP.classes [ B.fa, B.faSearch ] ] [] ] | |
] | |
] | |
eval :: Query ~> H.ComponentDSL State Query Message Aff | |
eval (Initialize next) = next <$ do | |
s <- H.get | |
trigger <- debouncedEventSource s.debounceTime | |
H.modify_ (_ { searchTrigger = Just trigger }) | |
eval (Finalize next) = next <$ do | |
s <- H.get | |
H.liftAff $ for_ s.searchTrigger cancelDebounceTrigger | |
eval (Search str next) = next <$ do | |
s <- H.get | |
let val = if null str || length str < s.minLength then Nothing else Just str | |
when (val /= s.search) $ do | |
H.modify_ (_ { search = val }) | |
case s.searchTrigger of | |
Nothing -> pure unit | |
Just tr -> H.liftAff $ runDebounceTrigger tr SendSearch | |
eval (SendSearch next) = next <$ do | |
s <- H.get | |
H.raise $ New s.search | |
eval (Receive i next) = next <$ do | |
s <- H.get | |
-- update only loading. | |
when (s.loading /= i.loading) $ | |
H.modify_ (_ { loading = i.loading }) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment