Metadata-Version: 2.1
Name: django-reactor
Version: 0.1.0a0
Summary: Brings LiveView from Phoenix framework into Django
Home-page: https://github.com/edelvalle/reactor
Author: Eddy Ernesto del Valle Pino
Author-email: eddy@edelvalle.me
License: BSD
Description: # Reactor, a LiveView library for Django
        
        Reactor enables you to do something similar to Phoenix framework LiveView using Django Channels.
        
        ## Installation and setup
        
        [Setup up your django-channels](https://channels.readthedocs.io/en/latest/installation.html) project before hand.
        
        Install reactor:
        
        ```bash
        pip install django-reactor
        ```
        
        Add `reactor` to your `INSALLED_APPS`. Register the URL patterns of reactor in your your file where is the ASGI application, usually `<youproject>/routing.py`, something like this:
        
        ```python
        from channels.auth import AuthMiddlewareStack
        from channels.routing import ProtocolTypeRouter, URLRouter
        
        from reactor.urls import websocket_urlpatterns  # <- import this
        
        application = ProtocolTypeRouter({
            'websocket': AuthMiddlewareStack(URLRouter(
                websocket_urlpatterns, # <- add it here
                ...
            ))
        })
        ```
        
        In the templates where you want to use reactive components you have to load the reactor static files. So do something like:
        
        ```html
        {% load reactor %}
        <!doctype html>
        <html>
          <head>
             ....
             {% reactor_header %}
          </head>
          ...
        </html>
        ```
        
        Put them as early as possible, they use `<script defer>` so they will be downloaded in parallel with the page load and when the page is loaded will be executed.
        
        ## Simple counter example
        
        In your app create a template `x-counter.html`:
        
        ```html
        {% load reactor %}
        <x-counter id="{{ this.id }}" state="{{ this.serialize|tojson }}">
          {{ this.amount }}
          <button onclick="send(this, 'inc')">+</button>
          <button onclick="send(this, 'dec')">-</button>
          <button onclick="send(this, 'set_to', {amount: 0})">reset</button>
        </x-counter>
        ```
        
        Anatomy of a template: each component should is a [custom web component](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) that inherits from [HTMLElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement). They should have an `id` so the backend knows which instance is this one and a `state` attribute with the necessary information to recreate the full state of the component on first render and in case of reconnection to the back-end.
        
        Render things as usually, so you can use full Django template language, `trans`, `if`, `for` and so on. Just keep in mind that the instance of the component is referred as `this`.
        
        Forwarding events to the back-end: Notice that for event binding in-line JavaScript is used on the event handler of the HTML elements. How this works? When the increment button receives a click event `send(this, 'inc')` is called, `send` is a reactor function that will look for the parent custom component and will dispatch to it the `inc` message, or the `set_to` message and its parameters `{amount: 0}`. The custom element then will send this message to the back-end, where the state of the component will change and then will be re-rendered back to the front-end. In the front-end `morphdom` (just like in Phoenix LiveView) is used to apply the new HTML.
        
        Now let's write the behavior part of the component
        
        ```python
        from reactor import Component
        
        class XCounter(Component):
            # reference the template from above
            template_name = 'x-counter.html' 
        
            # A component is instantiated during normal rendering and when the component
            # connects from the front-end. Then  __init__ is called passing `context` of
            # creation (in case of HTML  rendering is the context of the template, in
            # case of a WebSocket connection is the scope of django channels) Also the
            # `id` is passed if any is provided, otherwise a `uuid4` is  generated on
            # the fly.
        
            # This method is called after __init__ passing the initial state of the 
            # Component, this method is responsible taking the state of the component
            # and construct or reconstruct the component. Sometimes loading things from
            # the database like in the tood-demo app https://bit.ly/2ZlMvP3
            def mount(self, amount=0, **kwargs):
                self.amount = amount
        
            # This method is used to capture the essence of the state of a component
            # state, so it can be reconstructed at any given time on the future.
            # By passing what ever is returned by this method to `mount`
            def serialize(self):
                return dict(id=self.id, amount=self.amount)
        
            # This are the event handlers they always start with `receive_`
        
            def receive_inc(self, **kwargs):
                self.amount += 1
        
            def receive_dec(self, **kwargs):
                self.amount -= 1
        
            def receive_set_to(self, amount, **kwargs):
                self.amount = amount
        ```
        
        Let's now render this counter, expose a normal view that renders HTML, like:
        
        
        ```python
        def index(request):
            return render(request, 'index.html')
        ```
        
        And the index template being:
        
        ```html
        {% load reactor %}
        <!doctype html>
        <html>
          <head>
             ....
             {% reactor_header %}
          </head>
          <body>
            {% 'x-counter' %}
        
            <!-- or passing an initial state -->
            {% 'x-counter' amount=100 %}    
        
          </body>
        </html>
        ```
        
        Components can be nested, there is no problem with that. You just need to create one inside another.
        
Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Topic :: Internet :: WWW/HTTP
Requires-Python: >=3.6
Description-Content-Type: text/markdown
Provides-Extra: development
