************* Custom Gizmos ************* **Last Updated:** February 22, 2018 Tethys Extensions can be used to create custom gizmos, which can then be used by any app in portals where the extension is installed. This document will provide a brief overview of how to create a gizmo. Anatomy of a Gizmo ------------------ Gizmos are essentially mini-templates that can be embedded in other templates using the ``gizmo`` tag. They are composed of three primary components: #. Gizmo Options Class #. Gizmo Template #. JavaScript and CSS Dependencies Each component will be briefly introduced. To illustrate, we will show how a simplified version of the ``SelectInput`` gizmo could be implemented as a custom Gizmo in an extension. Gizmo Organization ------------------ The files used to define custom gizmos must be organized in a specific way in your app extension. Each gizmo options class must be located in its own python module and the file should be located in the ``gizmos`` package of your extension. The template for the gizmo must an HTML file located within the ``templates/gizmos/`` folder of your extension. Gizmo files must follow a specific naming convention: the python module containing the gizmo options class and the name of the gizmo template must have the same name as the gizmo. For example, if the name of the gizmo you are creating is ``custom_select_input`` then the name of the gizmo template would be ``custom_select_input.html`` and the name of the gizmo options module would be ``custom_select_input.py``. JavaScript and CSS dependencies should be stored in the ``public`` directory of your extension as usual or be publicly available from a CDN or similar. Dependencies stored locally can be organized however you prefer within the ``public`` directory. Finally, you must import the gizmo options class in the ``gizmos/__init__.py`` module. Only Gizmos imported here will be accessible. For the custom select input example, the file structure would look something like this: :: tethysext-my_first_extension/ |-- tethysext/ | |-- my_first_extension/ | | |-- gizmos/ | | | |-- custom_select_input.py | | |-- public/ | | | |-- gizmos/ | | | | |-- custom_select_input/ | | | | | |-- custom_select_input.css | | | | | |-- custom_select_input.js | | |-- templates/ | | | |-- gizmos/ | | | | |-- custom_select_input.html .. important:: Gizmo names must be globally unique within a portal. If a portal has two extensions that implement gizmos with the same name, they will conflict and likely not work properly. Gizmo Options Class ------------------- A gizmo options class is a class that inherits from the ``TethysGizmoOptions`` base class. It can be thought of as the context for the gizmo template. Any property or attribute of the gizmo options class will be available as a variable in the Gizmo Template. For the custom select input gizmo, create a new python module in the ``gizmos`` package called ``custom_select_input.py`` and add the following contents: :: from tethys_sdk.gizmos import TethysGizmoOptions class CustomSelectInput(TethysGizmoOptions): """ Custom select input gizmo. """ gizmo_name = 'custom_select_input' def __init__(self, name, display_text='', options=(), initial=(), multiselect=False, disabled=False, error='', **kwargs): """ constructor """ # Initialize parent super().__init__(**kwargs) # Initialize Attributes self.name = name self.display_text = display_text self.options = options self.initial = initial self.multiselect = multiselect self.disabled = disabled self.error = error It is important that ``gizmo_name`` property is the same as the name of the python module and template for the gizmo. Also, it is important to include ``**kwargs`` as an argument to your contstructor and use it to initialize the parent ``TethysGizmoOptions`` object. This will catch any of the parameters that are common to all gizmos like ``attributes`` and ``classes``. After defining the gizmo options class, import it in the ``gizmos/__init__.py`` module: :: from custom_select_input import CustomSelectInput Gizmo Template -------------- Gizmo templates are similar to the templates used for Tethys apps, but much simpler. For the custom select input gizmo, create a new template in the ``templates/gizmos/`` directory with the same name as your gizmo, ``custom_select_input.html``, with the following contents: .. code-block:: django {% load static %}
{{ error }}
{% endif %}