<div dir="ltr">Hello Alex -<div><br></div><div>Thank you for your response to my question here:</div><div><br></div><div><a href="http://www.impredicative.com/pipermail/ur/2015-July/002049.html">http://www.impredicative.com/pipermail/ur/2015-July/002049.html</a></div><div><br></div><div>I see from your website that you do consulting. If you are doing projects for clients using Ur/Web, then that must be very exciting.</div><div><br></div><div><br></div><div>Research so far:</div><div><br></div><div><div style="font-size:12.8000001907349px">I have been studying the example based on Mithril + RxJS </div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px"><span style="font-size:12.8000001907349px"><a href="http://www.ericponto.com/blog/2015/05/31/rxjs-and-mithril/">http://www.ericponto.com/blog/2015/05/31/rxjs-and-mithril/</a></span><br></div><div style="font-size:12.8000001907349px"><span style="font-size:12.8000001907349px"><br></span></div><div style="font-size:12.8000001907349px"><div style="font-size:12.8000001907349px">I imagine it might be quite similar to what one might code natively in Ur/Web FR<span style="font-size:12.8000001907349px">P). For example, see this code fragment (using Mithril + RxJS):</span></div><div style="font-size:12.8000001907349px"><span style="font-size:12.8000001907349px"><br></span></div><div style="font-size:12.8000001907349px"><pre style="overflow:auto;font-family:monospace,monospace;font-size:0.875em;color:rgb(147,161,161)"><code class="" style="font-family:monospace,monospace;font-size:1em;color:rgb(222,32,20)"><span class="" style="color:rgb(181,137,0)">controller</span><span class="" style="color:rgb(147,161,161)">()</span> <span class="" style="color:rgb(147,161,161)">{</span>
  <span class="" style="color:rgb(203,75,22)">this</span><span class="" style="color:rgb(147,161,161)">.</span><span class="" style="color:rgb(181,137,0)">model</span> <span class="" style="color:rgb(147,161,161);font-weight:700">=</span> <span class="" style="color:rgb(181,137,0)">m</span><span class="" style="color:rgb(147,161,161)">.</span><span class="" style="color:rgb(181,137,0)">prop</span><span class="" style="color:rgb(147,161,161)">({});</span>
    
  <span class="" style="color:rgb(181,137,0)">Rx</span><span class="" style="color:rgb(147,161,161)">.</span><span class="" style="color:rgb(181,137,0)">Observable</span><span class="" style="color:rgb(147,161,161)">.</span><span class="" style="color:rgb(181,137,0)">fromEvent</span><span class="" style="color:rgb(147,161,161)">(</span><span class="" style="color:rgb(181,137,0)">el</span><span class="" style="color:rgb(147,161,161)">,</span> <span class="" style="color:rgb(42,161,152)">"keyup"</span><span class="" style="color:rgb(147,161,161)">)</span>
    <span class="" style="color:rgb(147,161,161)">.</span><span class="" style="color:rgb(181,137,0)">map</span><span class="" style="color:rgb(147,161,161)">(</span><span class="" style="color:rgb(181,137,0)">pluck</span><span class="" style="color:rgb(147,161,161)">(</span><span class="" style="color:rgb(42,161,152)">"target"</span><span class="" style="color:rgb(147,161,161)">))</span>
    <span class="" style="color:rgb(147,161,161)">.</span><span class="" style="color:rgb(181,137,0)">filter</span><span class="" style="color:rgb(147,161,161)">(</span><span class="" style="color:rgb(181,137,0)">el</span> <span class="" style="color:rgb(147,161,161);font-weight:700">=></span> <span class="" style="color:rgb(181,137,0)">el</span><span class="" style="color:rgb(147,161,161)">.</span><span class="" style="color:rgb(181,137,0)">matches</span><span class="" style="color:rgb(147,161,161)">(</span><span class="" style="color:rgb(42,161,152)">"input"</span><span class="" style="color:rgb(147,161,161)">))</span>
    <span class="" style="color:rgb(147,161,161)">.</span><span class="" style="color:rgb(181,137,0)">map</span><span class="" style="color:rgb(147,161,161)">(</span><span class="" style="color:rgb(181,137,0)">pluck</span><span class="" style="color:rgb(147,161,161)">(</span><span class="" style="color:rgb(42,161,152)">"value"</span><span class="" style="color:rgb(147,161,161)">))</span>
    <span class="" style="color:rgb(147,161,161)">.</span><span class="" style="color:rgb(181,137,0)">filter</span><span class="" style="color:rgb(147,161,161)">(</span><span class="" style="color:rgb(181,137,0)">val</span> <span class="" style="color:rgb(147,161,161);font-weight:700">=></span> <span class="" style="color:rgb(181,137,0)">val</span><span class="" style="color:rgb(147,161,161)">.</span><span class="" style="color:rgb(181,137,0)">length</span> <span class="" style="color:rgb(147,161,161);font-weight:700">></span> <span class="" style="color:rgb(42,161,152)">2</span><span class="" style="color:rgb(147,161,161)">)</span>
    <span class="" style="color:rgb(147,161,161)">.</span><span class="" style="color:rgb(181,137,0)">debounce</span><span class="" style="color:rgb(147,161,161)">(</span><span class="" style="color:rgb(42,161,152)">250</span><span class="" style="color:rgb(147,161,161)">)</span>
    <span class="" style="color:rgb(147,161,161)">.</span><span class="" style="color:rgb(181,137,0)">distinctUntilChanged</span><span class="" style="color:rgb(147,161,161)">()</span>
    <span class="" style="color:rgb(147,161,161)">.</span><span class="" style="color:rgb(181,137,0)">flatMapLatest</span><span class="" style="color:rgb(147,161,161)">(</span><span class="" style="color:rgb(181,137,0)">searchGithub</span><span class="" style="color:rgb(147,161,161)">)</span>
    <span class="" style="color:rgb(147,161,161)">.</span><span class="" style="color:rgb(181,137,0)">subscribe</span><span class="" style="color:rgb(147,161,161)">(</span><span class="" style="color:rgb(203,75,22)">this</span><span class="" style="color:rgb(147,161,161)">.</span><span class="" style="color:rgb(181,137,0)">model</span><span class="" style="color:rgb(147,161,161)">);</span> 
<span class="" style="color:rgb(147,161,161)">}</span></code></pre></div><div><span style="font-size:12.8000001907349px">It looks very functional! So it might be straightforward to rewrite this in Ur/Web. (Although I would have no idea "where" to situate it within an overall _.ur module. Currently it is a call to a function, inside some JavaScript function called Controller(). I have no idea how this could correspond to code in Ur/Web.)</span></div><div><span style="font-size:12.8000001907349px"><br></span></div><div><span style="font-size:12.8000001907349px">Using FFI?</span></div></div><div style=""><span style="font-size:12.8000001907349px"><br></span></div><div style=""><span style="font-size:12.8000001907349px">I also had investigated two other possible approaches, involving using Ur/Web FFI to "wrap" an already existing full-fledged JavaScript library for autocomplete widgets, such as Select2 and twitter typeahead.js.</span></div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">I thought using FFI might also be a good strategy, since such existing libraries would probably be heavily optimized already, to work well with the browser and with the remote database.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">My initial attempts using these two approaches gave compile errors:</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px"><div style="font-size:12.8000001907349px"><a href="https://github.com/StefanScott/urweb-crudcrud/issues/1">https://github.com/StefanScott/urweb-crudcrud/issues/1</a></div><div style="font-size:12.8000001907349px"><a href="https://github.com/StefanScott/urweb-crudcrud/issues/2">https://github.com/StefanScott/urweb-crudcrud/issues/2</a></div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">Native FRP, versus foreign (FFI)</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">Do you really think it would be better to program an autocomplete widget natively using Ur/Web's FRP, rather than "wrapping" some existing, full-featured, heavily-optimized JavaScript library which already provides a nice autocomplete widget?</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">I understand there would be trade-offs using either approach (native or foreign). </div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">On the one hand, a native solution in Ur/Web would probably be simpler and more elegant - but I do not know how optimized Ur/Web's generated client-side code might be. I imagine that it would work fine though - and the code could probably be fairly short.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">On the other hand, it would seem to be unfortunate if Ur/Web should disregard all the fine JavaScript libraries already in existence. For example, much of Clojure's success is due to the fact that it runs on the JVM - so all Java libraries are automatically available in Clojure - providing the benefits of many person-years of labor.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">Whenever I post questions on the Mailing List, Adam usually says "it is better to just program this in Ur/Web - ignore the existing solutions in JavaScript".</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">But are all existing JavaScript libraries so bad, that we should simply re-write them all from scratch in Ur/Web? This doesn't seem realistic - particular in view of the small size of the community.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">I was hoping to simply use FFI and get the benefits of some existing full-fledged, heavily optimized JavaScript libraries for autocomplete widgets.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">But given the compiler errors shown in the two GitHub Issues links above, I have not been able to understand how to pursue the FFI approach.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">Elsewhere in this thread, Sergey has provided some pointers to code he wrote for using JavaScript libraries - as well as some functions Unsafe.s2xhead and Unsafe.s2xbody, which may help avoid some of the compile errors I was getting.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">I'm not much of a front-end or JavaScript programmer!</div></div></div><div><br></div><div>I should confess that I have never felt very comfortable reading JavaScript - and I have never written anything important using it. </div><div><br></div><div><div style="font-size:12.8000001907349px">It has has always been hard for me to understand the syntax and semantics of JavaScript (but easier to read things like CoffeeScript, Babel, ClojureScript, which use a more "functional" syntax). </div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px"><div style="font-size:12.8000001907349px">My experience is more in algebraic data types (I have used the Maude language a bit, and studied ML and Haskell a lot) and back-end (SQL) data modeling. </div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">So, I am not confident of my ability to write good code involving events, timing, throttling / debouncing, interactivity - all the stuff involved in front-end development. </div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">I perceive that these problems involve "co-algebraic process types" - the dual of my experience in algebraic data types.</div><div><br></div></div><div style="font-size:12.8000001907349px">But now I think perhaps must force myself to learn enough front-end programming just to get the few data-bound UI widgets I need to put on the front-end of all databases:</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">- autocomplete widget</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">- datagrid</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">- master-detail form layout (a "parent" datagrid linked to a "child" datagrid, via an SQL foreign key)</div></div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">Again, thank you for your encouragement. </div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">I am surprised that Ur/Web (which is specialized to work with databases) still lacks some kind of data-bound menu-widget to let the user select the value for a foreign-key.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">And given my lack of experience with front-end programming and JavaScript, I am probably the worst person to attempt to program this sort of thing.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">However, I am highly motivated to see this kind of autocomplete widget available, so I will continue to look for ways to do so.</div><div style="font-size:12.8000001907349px"><div><br></div><div>- Stefan Scott</div><div><br></div><div><br></div></div></div>