Search code examples
javascriptcodemirrorpurescriptpurescript-pux

How to generate Pux actions from a foreign module?


I'm trying to write an application using purescript-pux and CodeMirror, a static code editor.

CodeMirror makes an editor from a text-area, but the events are handled differently, therefore I cannot use the onChange function from Pux.Html.Events.

To handle input changes in a CodeMirror editor, one should do it this way:

CodemirrorInstance.on('change',function(cMirror){
  // get value right from instance
  var newValue = cMirror.getValue();
});

I'm able to make a Codemirror instance which is some trivial work. The problem I'm having is about how do I make pux aware of the events.

I have a Channel which I have subscribed to and I use for handling websocket messages, but I don't really know how could I send something over there from the foreign JavaScript file.


Solution

  • you maybe just need to setup a signal (purescript-signal ) on your foreign module.

    Maybe something like this:

    function CMChangeSignal(constant) {
        /** take initial value here if it  possible and pass it to constan fnt */
        var out = constant();
        // listen to it
        CodemirrorInstance.on('change',function(cMirror){
            // get value right from instance
            var newValue = cMirror.getValue();
            out.set(newValue);
        });
        return function () {
            return out;
        }
    }
    

    then on your purescript file:

    // type it, read the CodeMirror Docs.
    type CMChange = 
        { from :: CMCoordinate
          to :: CMCoordinate
          text :: Array String
          removed :: String
          origin :: ??
        }
    
    foreign import _CMChangeSignal :: forall eff change. (change -> Signal change) -> Eff (dom :: DOM | eff) (Signal CMChange)
    
    cmChanged :: forall eff. Eff (dom :: DOM | eff) (Signal CMChange)
    cmChanged = _CMChangeSignal constant
    
    main :: Eff (CoreEffects (dom :: DOM)) Unit
    main = do
      urlSignal <- sampleUrl
      let routeSignal = urlSignal ~> (PageView <<< match)
      -- create signal then map it to your Action
      cmSignal <- cmChanged
      let cmChangeSignal = cmSignal ~> CodeMirrorChangedAction
    
      app <- start
        { initialState: init
        , update: update
        , view: view
        , inputs: [routeSignal, cmChangeSignal]
        }
    
      renderToDOM "#app" app.html
    

    constant is function defined in "purescript-signal" that Pux depend.