<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ryan Morshead</title>
    <description>The latest articles on Forem by Ryan Morshead (@rmorshea).</description>
    <link>https://forem.com/rmorshea</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F222044%2Fca6a8c3a-e52c-4c7f-ae2b-a437d31d3ca9.png</url>
      <title>Forem: Ryan Morshead</title>
      <link>https://forem.com/rmorshea</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rmorshea"/>
    <language>en</language>
    <item>
      <title>IDOM - It's React, but in Python</title>
      <dc:creator>Ryan Morshead</dc:creator>
      <pubDate>Sat, 20 Feb 2021 01:16:31 +0000</pubDate>
      <link>https://forem.com/rmorshea/idom-it-s-react-but-in-python-39g1</link>
      <guid>https://forem.com/rmorshea/idom-it-s-react-but-in-python-39g1</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/idom-team/idom" rel="noopener noreferrer"&gt;IDOM&lt;/a&gt; is a new declarative Python package for building highly interactive user interfaces.&lt;/p&gt;

&lt;p&gt;The source is hosted on GitHub: &lt;a href="https://github.com/idom-team/idom" rel="noopener noreferrer"&gt;https://github.com/idom-team/idom&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;IDOM takes inspiration from &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt;, and wherever possible, attempts to achieve parity with the features it copies more directly. Nowhere is this more evident than the version of React's often lauded &lt;a href="https://reactjs.org/docs/hooks-intro.html" rel="noopener noreferrer"&gt;"Hooks"&lt;/a&gt; that IDOM implements in Python.&lt;/p&gt;

&lt;p&gt;At a glance, the similarities between IDOM and React are rather striking. Below is a React component which defines a simple &lt;code&gt;Counter&lt;/code&gt; displaying the number of times a button has been clicked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click me!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`Click count: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is the same component implemented in Python using IDOM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;idom&lt;/span&gt;

&lt;span class="nd"&gt;@idom.component&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;set_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;onClick&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;set_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Click me!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Click count: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which, when displayed in your browser, should look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frmorshea.github.io%2Farticles%2F2021%2Fidom-react-but-its-python%2Fclick-counter.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frmorshea.github.io%2Farticles%2F2021%2Fidom-react-but-its-python%2Fclick-counter.gif" alt="click-counter-example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Do We Need IDOM?
&lt;/h2&gt;

&lt;p&gt;Over the &lt;a href="https://www.npmtrends.com/react-vs-angular-vs-vue" rel="noopener noreferrer"&gt;past 5 years&lt;/a&gt; front-end developers seem to have concluded that programs written with a &lt;a href="https://www.youtube.com/watch?v=yGh0bjzj4IQ" rel="noopener noreferrer"&gt;declarative&lt;/a&gt; style or framework tend to be easier to understand and maintain than those done imperatively. Put more simply, mutable state in programs can quickly lead to unsustainable complexity. This trend is largely evidenced by the &lt;a href="https://gist.github.com/tkrotoff/b1caa4c3a185629299ec234d2314e190" rel="noopener noreferrer"&gt;rise&lt;/a&gt; of Javascript frameworks like &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue&lt;/a&gt; and &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt; which describe the logic of computations without explicitly stating their control flow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frmorshea.github.io%2Farticles%2F2021%2Fidom-react-but-its-python%2Fnpm-download-trends.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frmorshea.github.io%2Farticles%2F2021%2Fidom-react-but-its-python%2Fnpm-download-trends.png" alt="npm download trends"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So what does this have to do with Python and IDOM? Well, because browsers are the de facto "operating system of the internet", even back-end languages like Python have had to figure out clever ways to integrate with them. While standard &lt;a href="https://en.wikipedia.org/wiki/Representational_state_transfer" rel="noopener noreferrer"&gt;REST&lt;/a&gt; APIs are well suited to applications built using HTML templates, modern browser users expect a higher degree of interactivity than this alone can achieve.&lt;/p&gt;

&lt;p&gt;A variety of Python packages have since been created to help solve this problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/jupyter-widgets/ipywidgets" rel="noopener noreferrer"&gt;IPyWidgets&lt;/a&gt; - Adds interactive widgets to &lt;a href="https://jupyter.org/" rel="noopener noreferrer"&gt;Jupyter Notebooks&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://plotly.com/dash/" rel="noopener noreferrer"&gt;Dash&lt;/a&gt; - Allows data scientists to produces enterprise-ready analytic apps&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.streamlit.io/" rel="noopener noreferrer"&gt;Streamlit&lt;/a&gt; - Turns simple Python scripts into interactive dashboards&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.bokeh.org/" rel="noopener noreferrer"&gt;Bokeh&lt;/a&gt; - An interactive visualization library for modern web browsers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However they each have drawbacks that can make them difficult to use.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Restrictive ecosystems&lt;/strong&gt; - UI components developed for one framework cannot be easily ported to any of the others because their APIs are either too complex, undocumented, or are structurally inaccesible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Imperative paradigm&lt;/strong&gt; - IPyWidgets and Bokeh have not embraced the same declarative design principles pioneered by front-end developers. Streamlit and Dash on the otherhand, are declarative, but fall short of the features provided by React or Vue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limited layouts&lt;/strong&gt; - At their initial inception, the developers of these libraries were driven by the visualization needs of data scientists so the ability to create complex UI layouts may not have been a primary engineering goal.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A future article will address specific comparisons to each of the projects mentioned above, but for now, we'll just focus on IDOM and its solutions to these problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ecosystem Independence
&lt;/h2&gt;

&lt;p&gt;IDOM has a flexible set of core abstractions that allow it to interface with its peers. At the time of writing, both Jupyter and Dash are supported, while Streamlit and Bokeh are in the works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/idom-team/idom-jupyter" rel="noopener noreferrer"&gt;idom-jupyter&lt;/a&gt; (try it now with &lt;a href="https://mybinder.org/v2/gh/idom-team/idom-jupyter/main?filepath=notebooks%2Fintroduction.ipynb" rel="noopener noreferrer"&gt;Binder&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/idom-team/idom-dash" rel="noopener noreferrer"&gt;idom-dash&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By providing well defined interfaces and straighforward protocols, IDOM makes it easy to swap out any part of the stack with an alternate implementation if you want to. For example, if you need a different web server for your application, IDOM already has 3 options to choose from or, use as blueprints to create your own:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/sanic-org/sanic" rel="noopener noreferrer"&gt;Sanic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pallets/flask" rel="noopener noreferrer"&gt;Flask&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tornadoweb/tornado" rel="noopener noreferrer"&gt;Tornado&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can even target your usage of IDOM in your production-grade applications with IDOM's Javascript React client library](&lt;a href="https://www.npmjs.com/package/idom-client-react" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/idom-client-react&lt;/a&gt;). Just install it in your front-end app and connect to a back-end websocket that's serving up IDOM models. IDOM's own &lt;a href="https://idom-docs.herokuapp.com/docs/index.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; acts as a prime example for this targeted usage - most of the page is static HTML, but embedded in it are interactive examples that feature live views being served from a web socket:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frmorshea.github.io%2Farticles%2F2021%2Fidom-react-but-its-python%2Flive-examples-in-docs.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frmorshea.github.io%2Farticles%2F2021%2Fidom-react-but-its-python%2Flive-examples-in-docs.gif" alt="live-examples-in-docs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Declarative Components
&lt;/h2&gt;

&lt;p&gt;IDOM, by adopting the hook design pattern from React, inherits many of its aesthetic and functional characteristics. For those unfamiliar with hooks, user interfaces are composed of basic &lt;a href="https://en.wikipedia.org/wiki/HTML_element" rel="noopener noreferrer"&gt;HTML elements&lt;/a&gt; that are constructed and returned by special functions called "components". Then, through the magic of hooks, those component functions can be made to have state. Consider the component below which displays a basic representation of an &lt;a href="https://en.wikipedia.org/wiki/AND_gate" rel="noopener noreferrer"&gt;AND-gate&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;idom&lt;/span&gt;

&lt;span class="nd"&gt;@idom.component&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;AndGate&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;input_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;toggle_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;use_toggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;input_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;toggle_2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;use_toggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;checkbox&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;onClick&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;toggle_1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;checkbox&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;onClick&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;toggle_2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;input_1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; AND &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;input_2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;input_1&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;input_2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;use_toggle&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;set_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;toggle_state&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="nf"&gt;set_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;old_state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;old_state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;toggle_state&lt;/span&gt;

&lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AndGate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frmorshea.github.io%2Farticles%2F2021%2Fidom-react-but-its-python%2Fand-gate.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frmorshea.github.io%2Farticles%2F2021%2Fidom-react-but-its-python%2Fand-gate.gif" alt="and-gate-demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's a very high level summary of how it works... the first time a view of the component above is rendered, the &lt;code&gt;AndGate&lt;/code&gt; function is called where its initial &lt;code&gt;state&lt;/code&gt; for &lt;code&gt;input_1&lt;/code&gt; and &lt;code&gt;input_2&lt;/code&gt; is &lt;code&gt;False&lt;/code&gt;. The function then returns a series of HTML elements with callbacks that respond to client-side events. Machinery behind the scenes subsequently realizes that declaration and displays two checkbox buttons with the text &lt;code&gt;False AND False = False&lt;/code&gt;. Later, when a user clicks the now visible checkbox buttons, client-side events are triggered, the associated callbacks respond by inverting the old &lt;code&gt;state&lt;/code&gt; from &lt;code&gt;False&lt;/code&gt; to &lt;code&gt;True&lt;/code&gt;, and a re-render of the component is scheduled. When re-rendering, the function is again called, this time though, where &lt;code&gt;input_1&lt;/code&gt; and &lt;code&gt;input_2&lt;/code&gt; have been updated to reflect the new &lt;code&gt;state&lt;/code&gt;, thus causing the displayed text to change.&lt;/p&gt;

&lt;p&gt;In the code above, consider the fact that it never explicitely describes how to evolve the frontend view when events occur. Instead, it declares that, given a particular state, this is how the view should look. It's then IDOM's responsibility to figure out how to bring that declaration into being. This behavior of defining outcomes without stating the means by which to achieve them is what makes components in IDOM and React "declarative". For comparison, a hypothetical, and a more imperative approach to defining the same interface might look similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_and_gate&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;output_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;update_output_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;toggle_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
      &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="nf"&gt;update_output_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;checkbox&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;onClick&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;toggle_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;checkbox&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;onClick&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;toggle_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;output_text&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update_output_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{input_1} AND {input_2} = {output}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;input_1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;input_2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;make_and_gate&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this imperative incarnation there are several disadvantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Refactoring is difficult&lt;/strong&gt; - Functions are much more specialized to their particular usages in &lt;code&gt;make_and_gate&lt;/code&gt; and thus cannot be easily generalized. By comparison, &lt;code&gt;use_toggle&lt;/code&gt; from the declarative implementation could be applicable to any scenario where boolean indicators are toggled on and off.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No clear static relations&lt;/strong&gt; - There is no one section of code through which to discern the basic structure and behaviors of the view. This issue is exemplified by the fact that we must call &lt;code&gt;update_output_text&lt;/code&gt; from two different locations. Once in the body of &lt;code&gt;make_and_gate&lt;/code&gt; and again in the body of the callback &lt;code&gt;toggle_input&lt;/code&gt;. This means that, to understand what the &lt;code&gt;output_text&lt;/code&gt; might contain, we must also understand all the business logic that surrounds it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Referential links cause complexity&lt;/strong&gt; - To evolve the view, various callbacks must hold references to all the elements that they will update. At the outset this makes writing programs difficult since elements must be passed up and down the call stack wherever they are needed. Considered further though, it also means that a function layers down in the call stack can accidentally or intentionally impact the behavior of ostensibly unrelated parts of the program.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Virtual Document Object Model
&lt;/h2&gt;

&lt;p&gt;To communicate between their back-end Python servers and Javascript clients, IDOM's peers take an approach that aligns fairly closely with the &lt;a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" rel="noopener noreferrer"&gt;Model-View-Controller&lt;/a&gt; design pattern - the controller lives server-side (though not always), the model is what's synchronized between the server and client, and the view is run client-side in Javascript. To draw it out might look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frmorshea.github.io%2Farticles%2F2021%2Fidom-react-but-its-python%2Fmvc-flow-diagram.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frmorshea.github.io%2Farticles%2F2021%2Fidom-react-but-its-python%2Fmvc-flow-diagram.svg" alt="mvc-flow-diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By contrast, IDOM uses something called a Virtual Document Object Model (&lt;a href="https://idom-docs.herokuapp.com/docs/specifications.html#vdom-mimetype" rel="noopener noreferrer"&gt;VDOM&lt;/a&gt;) to construct a representation of the view. The VDOM is constructed on the Python side by components then, as it evolves, IDOM's layout computes VDOM-diffs and wires them to its Javascript client where it is ultimately displayed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frmorshea.github.io%2Farticles%2F2021%2Fidom-react-but-its-python%2Fidom-flow-diagram.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frmorshea.github.io%2Farticles%2F2021%2Fidom-react-but-its-python%2Fidom-flow-diagram.svg" alt="idom-flow-diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This process, in addition to drastically reducing complexity, means that Python developers with just a little bit of HTML and CSS knowledge can easily create elabortate interfaces because they have complete control over the view. Of course many users probably don't care about the details and just want high level components, but for those who do, it's easy to distribute their creations for others to use in Python packages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Javascript Components
&lt;/h2&gt;

&lt;p&gt;If you're thinking critically about IDOM's use of a virtual DOM, you may have thought...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Isn't wiring a virtual representation of the view to the client, even if its diffed, expensive?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And yes, while the performance of IDOM is sufficient for most use cases, there are inevitably scenarios where this could be an issue. Thankfully though, just like its peers, IDOM makes it possible to seemlesly integrate &lt;a href="https://idom-docs.herokuapp.com/docs/javascript-components.html" rel="noopener noreferrer"&gt;Javascript components&lt;/a&gt;. They can be &lt;a href="https://github.com/idom-team/idom-react-component-cookiecutter" rel="noopener noreferrer"&gt;custom built&lt;/a&gt; for your use case, or you can just leverage the existing Javascript ecosystem without any extra work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;idom&lt;/span&gt;

&lt;span class="n"&gt;material_ui&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;install&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@material-ui/core&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;loading...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@idom.component&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;DisplaySliderEvents&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;set_event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;material_ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Slider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;color&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;primary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;step&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultValue&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;valueLabelDisplay&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;auto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;onChange&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;set_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DisplaySliderEvents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frmorshea.github.io%2Farticles%2F2021%2Fidom-react-but-its-python%2Fmaterial-ui-slider.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frmorshea.github.io%2Farticles%2F2021%2Fidom-react-but-its-python%2Fmaterial-ui-slider.gif" alt="material-ui-slider-demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Take Away
&lt;/h2&gt;

&lt;p&gt;Building highly interactive web applications as a Python developer has historically been a great challenge. However IDOM changes that. Knowing just basic HTML, CSS, and Python, you can make everything from &lt;a href="https://idom-docs.herokuapp.com/docs/examples.html#slideshow" rel="noopener noreferrer"&gt;slideshows&lt;/a&gt; to &lt;a href="https://idom-docs.herokuapp.com/docs/examples.html#simple-dashboard" rel="noopener noreferrer"&gt;dashboards&lt;/a&gt; and use it wherever you need it, whether that's in a &lt;a href="https://github.com/idom-team/idom-jupyter" rel="noopener noreferrer"&gt;Jupyter Notebook&lt;/a&gt; or an existing web application.&lt;/p&gt;

&lt;p&gt;To learn more check out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/idom-team/idom" rel="noopener noreferrer"&gt;the source code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://idom-docs.herokuapp.com/docs/installation.html" rel="noopener noreferrer"&gt;installation instructions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://idom-docs.herokuapp.com/docs/getting-started.html" rel="noopener noreferrer"&gt;understanding components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://idom-docs.herokuapp.com/docs/examples.html" rel="noopener noreferrer"&gt;interactive examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://idom-docs.herokuapp.com/docs/index.html" rel="noopener noreferrer"&gt;and much more&lt;/a&gt;!&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Simple Slides with Markdown and Python</title>
      <dc:creator>Ryan Morshead</dc:creator>
      <pubDate>Thu, 29 Oct 2020 07:30:55 +0000</pubDate>
      <link>https://forem.com/rmorshea/simple-slides-with-markdown-and-python-4909</link>
      <guid>https://forem.com/rmorshea/simple-slides-with-markdown-and-python-4909</guid>
      <description>&lt;h1&gt;
  
  
  The Pain of PowerPoint
&lt;/h1&gt;

&lt;p&gt;As a software developer, it's never fun to try and present my work using slides. Despite the bloat of tools like PowerPoint, when I'm trying to present code, they still somehow end up feeling restrictive. I find myself spending ages trying to center and format text all while shimming in screenshots of my code when I should really be focusing on the content of my presentation.&lt;/p&gt;

&lt;p&gt;So over a few weekends I set out to create tool that would:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Split a Markdown document into slides on each new title&lt;/li&gt;
&lt;li&gt;Convert the Markdown slides into HTML&lt;/li&gt;
&lt;li&gt;Serve up the HTML using a simple web server&lt;/li&gt;
&lt;li&gt;Be able to embed interactive widgets into slides&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Slidedown
&lt;/h1&gt;

&lt;p&gt;To satisfy the above goals I created &lt;a href="https://github.com/rmorshea/slidedown" rel="noopener noreferrer"&gt;Slidedown&lt;/a&gt;, a simple, &lt;code&gt;pip&lt;/code&gt; installable, Python-based command line tool that can turn Markdown documents like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;

&lt;span class="gh"&gt;# Step 1&lt;/span&gt;

Create an awesome slide deck.

&lt;span class="gh"&gt;# Step 2&lt;/span&gt;

Present it to awesome people.

&lt;span class="gh"&gt;# Step 3&lt;/span&gt;

Profit?&lt;span class="sb"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Into slides like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Frmorshea%2Fslidedown%2Fraw%2Fmaster%2Fdocs%2Fsimple-slide-example.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Frmorshea%2Fslidedown%2Fraw%2Fmaster%2Fdocs%2Fsimple-slide-example.gif" alt="slides-gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With one simple CLI command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

slidedown README.md


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Embedding Interactive Widgets
&lt;/h1&gt;

&lt;p&gt;Slidedown was built on top of another one of my projects called &lt;a href="https://idom-docs.herokuapp.com/docs/index.html" rel="noopener noreferrer"&gt;IDOM&lt;/a&gt; - a package that blurs the lines between Javascript and Python. IDOM allows you to create highly interactive web pages without writing a single line of Javascript.&lt;/p&gt;

&lt;p&gt;In Slidedown I've used it to enable you to embed interactive widgets into your slides in pure Python. With the following markup:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;

&lt;span class="gh"&gt;# Hello IDOM!&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-idom=&lt;/span&gt;&lt;span class="s"&gt;"hello.py"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="sb"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and a script &lt;code&gt;hello.py&lt;/code&gt; containing:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;idom&lt;/span&gt;

&lt;span class="nd"&gt;@idom.element&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;hi_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;set_hi_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;idom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;onClick&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;set_hi_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hi_count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;IDOM said hi &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hi_count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; time(s)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;you'll display a slide with an interactive button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Frmorshea%2Fslidedown%2Fraw%2Fmaster%2Fdocs%2Fslidedown-hello-idom.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Frmorshea%2Fslidedown%2Fraw%2Fmaster%2Fdocs%2Fslidedown-hello-idom.gif" alt="embedding-idom-gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The possibilities with IDOM are limitless. You can embed everything from data dashboards to games. To see even more, check out some &lt;a href="https://idom-docs.herokuapp.com/docs/examples.html" rel="noopener noreferrer"&gt;examples&lt;/a&gt; and be sure to try out the live examples!&lt;/p&gt;

&lt;h1&gt;
  
  
  Sharing Slides?
&lt;/h1&gt;

&lt;p&gt;The beauty of using Markdown is that to share it, you can just create a repo on GitHub, GitLab, or BitBucket and upload your slides as a &lt;code&gt;README.md&lt;/code&gt; that you can link to. All the resources for your slides (e.g. images) are also as easily accessible in the very same repository.&lt;/p&gt;

&lt;p&gt;Of course if you have any embedded widgets then those won't be displayed on you're repo's page. On the other hand though, if you were using PowerPoint you wouldn't have those anyway, so it's not such a huge loss. However if you colleagues know how to clone your repository and &lt;code&gt;pip&lt;/code&gt; install &lt;code&gt;slidedown&lt;/code&gt; then all it takes is one simple command to run your slides locally for themselves.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;If you ✍️ Slides&lt;/li&gt;
&lt;li&gt;you 😠 PowerPoint&lt;/li&gt;
&lt;li&gt;and you ❤️ Markdown&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then you should give &lt;a href="https://github.com/rmorshea/slidedown" rel="noopener noreferrer"&gt;Slidedown&lt;/a&gt; a try.&lt;/p&gt;

</description>
      <category>python</category>
      <category>productivity</category>
    </item>
    <item>
      <title>IDOM - Server Side Rendering in Python</title>
      <dc:creator>Ryan Morshead</dc:creator>
      <pubDate>Mon, 11 Nov 2019 21:45:04 +0000</pubDate>
      <link>https://forem.com/rmorshea/idom-server-side-rendering-with-python-49al</link>
      <guid>https://forem.com/rmorshea/idom-server-side-rendering-with-python-49al</guid>
      <description>&lt;p&gt;Ever wish you could write client-side Python? Well here's the next best thing, a server-side rendering solution implemented in pure Python! Check out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="//idom-docs.herokuapp.com/"&gt;documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;An &lt;a href="https://mybinder.org/v2/gh/idom-team/idom-jupyter/main?urlpath=lab/tree/notebooks/introduction.ipynb"&gt;interactive demo&lt;/a&gt; using Jupyter Notebooks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8PeBK93l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/vws91it2g42aejazki2h.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8PeBK93l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/vws91it2g42aejazki2h.gif" alt="Alt Text" width="522" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>react</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
