Skip to main content

mopyx

Project description

mopyx is a MobX/Vue inspired reactive model driven UI library. UI Toolkit independent.

Installation

pip install mopyx

Usage

from mopyx import render, render_call, model, action


@model
class RootModel:
    def __init__(self):
        self.name = "initial name"        # Whenever `name`, `desc` or `title` change,
        self.desc = "initial description" # a rerender will be triggered. This is
        self.title = "initial title"      # mapped in the actual rendering. Changing
        self.other = "initial other"      # `other` will not trigger a rerender.


class UpdateModelService:
    # Each model change is a tiny action that should trigger a rerender. To cluster
    # multiple actions together you can use `@action`. When the topmost `@action`
    # returns only then the affected renderers will be invoked.
    @action
    def update_title_and_description(title, description):
        self.model.title = title
        self.model.desc = description


class UiLabel:  # a basic label in any toolkit
    def __init__(self):
        self.label = None

    def set_label(self, label):
        self.label = label


class UiComponent:
    def __init__(self, model):
        self.model = model

        self.name = UiLabel()
        self.description = UiLabel()
        self.title = None

        self.update_data()

    # MoPyX will know about this rendering. Here it learns that from the
    # model, `name`, `desc`, and `title` are needed for the rendering.
    # After this render whenever any of the model properties change,
    # the `@render` method will be invoked automatically.
    @render
    def update_data(self):
        render_call(lambda: self.name.set_label(self.model.name))
        render_call(lambda: self.description.set_label(self.model.desc))

        self.title = self.model.title

You decorate your UI rendering functions with @render, or invoke them with render_call. MoPyX will map what render method used what properties in the model.

You decorate your model classes with @model. Whenever properties change in the model, the @render function will be called again, but only for the UI components that are affected by the model action. This will happen for every property in the model.

In the example above, if the name changes, then only the set_label will be invoked on the label, because it’s registered as a subcomponent rendering. If both title and name change simultaneously into an @action MoPyX will call only the top update_data rendering.

If they’re not wrapped in an action, every property is considered an action, so two renderings will trigger. To improve performance you can wrap multiple model updates into a single @action. An action method can call other methods, including other @action ones, then when the top most @action returns the rendering will be invoked.

In order to optimize the number of UI updates, only the relevant @render functions will be called, not always the topmost one.

If there is a component that’s too difficult to have its own @render for updates, you can also call the updates for that specific component using render_call() that will just wrap the given callable into a @render. For example if there is a Label component of some sort, you can just wrap it in render_calls:

render_call(lambda: self.name.set_label(self.model.name))

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mopyx-0.1.1.tar.gz (5.0 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page