Skip to content

Commit

Permalink
reorganize creating-interfaces + add info on fragments (#685)
Browse files Browse the repository at this point in the history
  • Loading branch information
rmorshea authored Feb 25, 2022
1 parent fdad4fd commit 2a54b34
Show file tree
Hide file tree
Showing 17 changed files with 102 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
HTML With IDOM
==============

In a typical Python-base web application the resonsibility of defining the view along
In a typical Python-base web application the responsibility of defining the view along
with its backing data and logic are distributed between a client and server
respectively. With IDOM, both these tasks are centralized in a single place. This is
done by allowing HTML interfaces to be constructed in Python. Take a look at the two
code examples below. The one on the left shows how to make a basic title and todo list
using standard HTML, the one of the right uses IDOM in Python, and below is a view of
what the HTML would look like if displayed:
code examples below. The first one shows how to make a basic title and todo list using
standard HTML, the second uses IDOM in Python, and below is a view of what the HTML
would look like if displayed:

.. grid:: 1 1 2 2
:margin: 0
:padding: 0

.. grid-item::
:columns: 6

.. code-block:: html

Expand All @@ -25,7 +24,6 @@ what the HTML would look like if displayed:
</ul>

.. grid-item::
:columns: 6

.. testcode::

Expand Down Expand Up @@ -86,7 +84,7 @@ to specify a URL to its ``src`` and use some ``style`` to modify and position it

In IDOM we add these attributes to elements using dictionaries. There are some notable
differences though. The biggest being the fact that all names in IDOM use ``camelCase``
instead of dash-sepearted words. For example, ``margin-left`` becomes ``marginLeft``.
instead of dash-separated words. For example, ``margin-left`` becomes ``marginLeft``.
Additionally, instead of specifying ``style`` using a string, we use a dictionary:

.. testcode::
Expand Down
22 changes: 11 additions & 11 deletions docs/source/creating-interfaces/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ Creating Interfaces
.. toctree::
:hidden:

html-with-idom
your-first-components
rendering-data
html-with-idom/index
your-first-components/index
rendering-data/index

.. dropdown:: :octicon:`bookmark-fill;2em` What You'll Learn
:color: info
Expand All @@ -16,20 +16,20 @@ Creating Interfaces
.. grid:: 1 2 2 2

.. grid-item-card:: :octicon:`code-square` HTML with IDOM
:link: html-with-idom
:link: html-with-idom/index
:link-type: doc

Construct HTML layouts from the basic units of user interface functionality.

.. grid-item-card:: :octicon:`package` Your First Components
:link: your-first-components
:link: your-first-components/index
:link-type: doc

Define reusable building blocks that it easier to construct complex
interfaces.

.. grid-item-card:: :octicon:`database` Rendering Data
:link: rendering-data
:link: rendering-data/index
:link-type: doc

Use data to organize and render HTML elements and components.
Expand Down Expand Up @@ -75,7 +75,7 @@ To recreate the same thing in IDOM you would write:
)
.. card::
:link: html-with-idom
:link: html-with-idom/index
:link-type: doc

:octicon:`book` Read More
Expand All @@ -94,10 +94,10 @@ create them we need to add an ``@component`` `decorator
<https://realpython.com/primer-on-python-decorators/>`__. To see what this looks like in
practice we'll quickly make a ``Photo`` component:

.. idom:: _examples/simple_photo
.. idom:: your-first-components/_examples/simple_photo

.. card::
:link: your-first-components
:link: your-first-components/index
:link-type: doc

:octicon:`book` Read More
Expand All @@ -116,10 +116,10 @@ from data in this way must be orgnized with :ref:`"keys" <Organizing Items With
One case where we might want to do this is if items in a todo list come from a list of
data that we want to sort and filter:

.. idom:: _examples/todo_list_with_keys
.. idom:: rendering-data/_examples/todo_list_with_keys

.. card::
:link: rendering-data
:link: rendering-data/index
:link-type: doc

:octicon:`book` Read More
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
def Photo(alt_text, image_id):
return html.img(
{
"src": f"https://picsum.photos/id/{image_id}/500/300",
"src": f"https://picsum.photos/id/{image_id}/500/200",
"style": {"width": "50%"},
"alt": alt_text,
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from idom import component, html, run


@component
def MyTodoList():
return html.div(
html.h1("My Todo List"),
html.img({"src": "https://picsum.photos/id/0/500/300"}),
html.ul(html.li("The first thing I need to do is...")),
)


run(MyTodoList)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from idom import component, html, run


@component
def MyTodoList():
return html._(
html.h1("My Todo List"),
html.img({"src": "https://picsum.photos/id/0/500/200"}),
html.ul(html.li("The first thing I need to do is...")),
)


run(MyTodoList)
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,63 @@ component once and use it wherever and however you need to:
.. idom:: _examples/nested_photos


Return a Single Root Element
----------------------------

Components must return a "single root element". That one root element may have children,
but you cannot for example, return a list of element from a component and expect it to
be rendered correctly. If you want to return multiple elements you must wrap them in
something like a :func:`html.div <idom.html.div>`:

.. idom:: _examples/wrap_in_div

If don't want to add an extra ``div`` you can use a "fragment" instead with the
:func:`html._ <idom.html._>` function:

.. idom:: _examples/wrap_in_fragment

Fragments allow you to group elements together without leaving any trace in the UI. For
example, the first code sample written with IDOM will produce the second HTML code
block:

.. grid:: 1 2 2 2
:margin: 0
:padding: 0

.. grid-item::

.. testcode::

from idom import html

html.ul(
html._(
html.li("Group 1 Item 1"),
html.li("Group 1 Item 2"),
html.li("Group 1 Item 3"),
),
html._(
html.li("Group 2 Item 1"),
html.li("Group 2 Item 2"),
html.li("Group 2 Item 3"),
)
)

.. grid-item::

.. code-block:: html

<ul>
<li>Group 1 Item 1</li>
<li>Group 1 Item 2</li>
<li>Group 1 Item 3</li>
<li>Group 2 Item 1</li>
<li>Group 2 Item 2</li>
<li>Group 2 Item 3</li>
</ul>



Parametrizing Components
------------------------

Expand Down
2 changes: 1 addition & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ combine these elements into reusable :ref:`"components" <your first components>`
sections that follow you'll learn how these UI elements are created and organized into
components. Then, you'll use this knowledge to create interfaces from raw data:

.. idom:: creating-interfaces/_examples/todo_list_with_keys
.. idom:: creating-interfaces/rendering-data/_examples/todo_list_with_keys

.. card::
:link: creating-interfaces/index
Expand Down
2 changes: 1 addition & 1 deletion tests/test_core/test_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1161,5 +1161,5 @@ def SetStateDuringRender():
assert render_count.current == 2

# there should be no more renders to perform
with pytest.raises(asyncio.exceptions.TimeoutError):
with pytest.raises(asyncio.TimeoutError):
await asyncio.wait_for(layout.render(), timeout=0.1)

0 comments on commit 2a54b34

Please sign in to comment.