Preventing default event with halogen

012
halogen

#1

How would we prevent the default onClick event in halogen?
I’ve found https://github.com/slamdata/purescript-halogen/issues/426
But Dom.Classy doesn’t seem to exist for 0.12, how would we preventDefault in a 0.12 world?


#2

Here is the simplest way to do it I think:

import Web.Event.Event (preventDefault)
import Web.HTML.Event.DragEvent as DragEvent -- for example
import Halogen as H

-- somewhere in `eval`:
let event = DragEvent.toEvent e
H.liftEffect $ preventDefault event

#3

Thanks for your response!. I’m not 100% sure how to integrate it. Below is what I have.

I think I was expecting it to be part of the render function. Seeing it in eval confused me :slight_smile:

module Header where
import Prelude
import Data.Maybe (Maybe(..))
import Halogen as H
import Halogen.HTML as HH
import Halogen.HTML.Events as HE
import Halogen.HTML.Properties as HP

data State = Home | About

data Query a = 
    GoTo State a
    | IsIn (State -> a)

data Message = ChangeState State

header :: forall m. H.Component HH.HTML Query Unit Message m
header = 
    H.component
        { initialState: const initialState
        , render
        , eval
        , receiver: const Nothing
        }
    where
    initialState :: State
    initialState = Home

    render:: State -> H.ComponentHTML Query
    render state = 
        HH.div_ [
            anchor "#home" Home "Home"
            , anchor "#about" About "About" 
            ,statetext   
        ]
        where 
        anchor href query text = 
            HH.a [HP.href href,  (HE.input_ (GoTo query))] [HH.text text]
        statetext = case state of
                            Home -> HH.text "Home"
                            About -> HH.text "About"
    
    eval:: Query ~> H.ComponentDSL State Query Message m
    eval = case _ of
        GoTo state next -> do
            H.put state
            pure next
        IsIn reply -> do   
            state <- H.get
            pure (reply state)

#4

Ah, sure! First, here are some imports required for the example below:

import Web.Event.Event (Event)
import Web.Event.Event as Event
import Web.UIEvent.MouseEvent (toEvent)

Ok, so the query might to look like this:

data Query a
    = GoTo State a
    | IsIn (State -> a)
    | PreventDefault Event (Query a)

We’ll need a MonadEffect constraint for your component + a helper function like Thomas suggested here https://github.com/slamdata/purescript-halogen/issues/426#issuecomment-320390523:

header :: forall m. MonadEffect m => H.Component HH.HTML Query Unit Message m
header = ...
  where
  preventClick q = HE.onClick \e -> Just $ PreventDefault (toEvent e) $ H.action q

Let’s do the eval part first:

    eval = case _ of
      ...
      PreventDefault e q → do
        H.liftEffect $ Event.preventDefault e
        eval q

Finally, we’ll use the preventClick in the render function like this:

        [ ...
        , HH.a
          [ HP.href "#href"
          , preventClick (GoTo 1)
          ]
          [ HH.text "smth" ]
        , ...
        ]

Here is another example from my app that I’m currently working on: https://gist.github.com/vyorkin/6c837b722a03c2a230db0cbbfbcbb7b6


#5

Thanks for the detailed description!. I’ve incorporated what you suggested into my toy app, and have it working. The link to the gist was really helpful too!. It’s good to see how you are meant to start thinking with using halogen :slight_smile: