diff --git a/examples/assets/template_areas.png b/examples/assets/template_areas.png new file mode 100644 index 0000000000..f53a9099c2 Binary files /dev/null and b/examples/assets/template_areas.png differ diff --git a/examples/reference/templates/Bootstrap.ipynb b/examples/reference/templates/Bootstrap.ipynb index 1f41e15778..eb8492bc47 100644 --- a/examples/reference/templates/Bootstrap.ipynb +++ b/examples/reference/templates/Bootstrap.ipynb @@ -17,14 +17,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "For a large variety of use cases we do not need complete control over the exact layout of each individual component on the page, as could be achieved with a [custom template](../../user_guide/Templates.ipynb), we just want to achieve a more polished look and feel. For these cases Panel ships with a number of default templates, which are defined by declaring three main content areas on the page, which can be populated as desired:\n", + "For a large variety of use cases we do not need complete control over the exact layout of each individual component on the page, as could be achieved with a [custom template](../../user_guide/Templates.ipynb), we just want to achieve a more polished look and feel. For these cases Panel ships with a number of default templates, which are defined by declaring four main content areas on the page, which can be populated as desired:\n", "\n", "* **`header`**: The header area of the HTML page\n", "* **`sidebar`**: A collapsible sidebar\n", "* **`main`**: The main area of the application\n", "* **`modal`**: A modal area which can be opened and closed from Python\n", "\n", - "These three areas behave very similarly to other Panel layout components and have list-like semantics. This means we can easily append new components into these areas. Unlike other layout components however, the contents of the areas is fixed once rendered. If you need a dynamic layout you should therefore insert a regular Panel layout component (e.g. a `Column` or `Row`) and modify it in place once added to one of the content areas. \n", + "These four areas behave very similarly to other Panel layout components and have list-like semantics. This means we can easily append new components into these areas. Unlike other layout components however, the contents of the areas is fixed once rendered. If you need a dynamic layout you should therefore insert a regular Panel layout component (e.g. a `Column` or `Row`) and modify it in place once added to one of the content areas. \n", "\n", "Templates can allow for us to quickly and easily create web apps for displaying our data. Panel comes with a default Template, and includes multiple Templates that extend the default which add some customization for a better display.\n", "\n", diff --git a/examples/reference/templates/FastGridTemplate.ipynb b/examples/reference/templates/FastGridTemplate.ipynb index 1366c25206..70d977af0b 100644 --- a/examples/reference/templates/FastGridTemplate.ipynb +++ b/examples/reference/templates/FastGridTemplate.ipynb @@ -24,7 +24,7 @@ "* **`main`**: The main area of the application\n", "* **`modal`**: A modal area which can be opened and closed from Python\n", "\n", - "These three areas behave very similarly to other Panel layout components. In particular the header, sidebar and modal behave just like the list-like `Row`/`Column` layouts while the main area behaves like a `GridSpec`. This means we can easily append new components into these areas. Unlike other layout components however, the contents of the areas is fixed once rendered. If you need a dynamic layout you should therefore insert a regular Panel layout component (e.g. a `Column` or `Row`) and modify it in place once added to one of the content areas. \n", + "These four areas behave very similarly to other Panel layout components. In particular the header, sidebar and modal behave just like the list-like `Row`/`Column` layouts while the main area behaves like a `GridSpec`. This means we can easily append new components into these areas. Unlike other layout components however, the contents of the areas is fixed once rendered. If you need a dynamic layout you should therefore insert a regular Panel layout component (e.g. a `Column` or `Row`) and modify it in place once added to one of the content areas. \n", "\n", "Templates can allow for us to quickly and easily create web apps for displaying our data. Panel comes with a default Template, and includes multiple Templates that extend the default which add some customization for a better display.\n", "\n", diff --git a/examples/reference/templates/FastListTemplate.ipynb b/examples/reference/templates/FastListTemplate.ipynb index 01a750be7f..febe5f75ea 100644 --- a/examples/reference/templates/FastListTemplate.ipynb +++ b/examples/reference/templates/FastListTemplate.ipynb @@ -17,14 +17,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "For a large variety of use cases we do not need complete control over the exact layout of each individual component on the page, as could be achieved with a [custom template](../../user_guide/Templates.ipynb), we just want to achieve a more polished look and feel. For these cases Panel ships with a number of default templates, which are defined by declaring three main content areas on the page, which can be populated as desired:\n", + "For a large variety of use cases we do not need complete control over the exact layout of each individual component on the page, as could be achieved with a [custom template](../../user_guide/Templates.ipynb), we just want to achieve a more polished look and feel. For these cases Panel ships with a number of default templates, which are defined by declaring four main content areas on the page, which can be populated as desired:\n", "\n", "* **`header`**: The header area of the HTML page\n", "* **`sidebar`**: A collapsible sidebar\n", "* **`main`**: The main area of the application\n", "* **`modal`**: A modal area which can be opened and closed from Python\n", "\n", - "These three areas behave very similarly to other Panel layout components and have list-like semantics. This means we can easily append new components into these areas. Unlike other layout components however, the contents of the areas is fixed once rendered. If you need a dynamic layout you should therefore insert a regular Panel layout component (e.g. a `Column` or `Row`) and modify it in place once added to one of the content areas. \n", + "These four areas behave very similarly to other Panel layout components and have list-like semantics. This means we can easily append new components into these areas. Unlike other layout components however, the contents of the areas is fixed once rendered. If you need a dynamic layout you should therefore insert a regular Panel layout component (e.g. a `Column` or `Row`) and modify it in place once added to one of the content areas. \n", "\n", "Templates can allow for us to quickly and easily create web apps for displaying our data. Panel comes with a default Template, and includes multiple Templates that extend the default which add some customization for a better display.\n", "\n", diff --git a/examples/reference/templates/GoldenLayout.ipynb b/examples/reference/templates/GoldenLayout.ipynb index ae8eeb53e6..764ece7eb4 100644 --- a/examples/reference/templates/GoldenLayout.ipynb +++ b/examples/reference/templates/GoldenLayout.ipynb @@ -3,28 +3,27 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], "source": [ "import panel as pn\n", "import numpy as np\n", "import holoviews as hv\n", "\n", "pn.extension(sizing_mode = 'stretch_width')" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ - "For a large variety of use cases we do not need complete control over the exact layout of each individual component on the page, as could be achieved with a [custom template](../../user_guide/Templates.ipynb), we just want to achieve a more polished look and feel. For these cases Panel ships with a number of default templates, which are defined by declaring three main content areas on the page, which can be populated as desired:\n", + "For a large variety of use cases we do not need complete control over the exact layout of each individual component on the page, as could be achieved with a [custom template](../../user_guide/Templates.ipynb), we just want to achieve a more polished look and feel. For these cases Panel ships with a number of default templates, which are defined by declaring four main content areas on the page, which can be populated as desired:\n", "\n", "* **`header`**: The header area of the HTML page\n", "* **`sidebar`**: A collapsible sidebar\n", "* **`main`**: The main area of the application\n", "* **`modal`**: A modal area which can be opened and closed from Python\n", "\n", - "These three areas behave very similarly to other Panel layout components and have list-like semantics. This means we can easily append new components into these areas. Unlike other layout components however, the contents of the areas is fixed once rendered. If you need a dynamic layout you should therefore insert a regular Panel layout component (e.g. a `Column` or `Row`) and modify it in place once added to one of the content areas. \n", + "These four areas behave very similarly to other Panel layout components and have list-like semantics. This means we can easily append new components into these areas. Unlike other layout components however, the contents of the areas is fixed once rendered. If you need a dynamic layout you should therefore insert a regular Panel layout component (e.g. a `Column` or `Row`) and modify it in place once added to one of the content areas. \n", "\n", "Templates can allow for us to quickly and easily create web apps for displaying our data. Panel comes with a default Template, and includes multiple Templates that extend the default which add some customization for a better display.\n", "\n", @@ -43,20 +42,19 @@ "* **`sidebar_width`** (int): The width of the sidebar in percent. Default is 20.\n", "\n", "________" - ] + ], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ - "In this case we are using the `GoldenTemplate`, built using the Golden Layout CSS, which allows for the creation of tabs that can be moved around. Due to the movable tabs this Template is a little different than the others. The sidebar works similarly to the other templates, but to have your displays render in different tabs, we have to make separate calls to `.main.append()`. Here is an example of how you can set up a display using this template:" - ] + "In this case we are using the `GoldenTemplate`, built using the [Golden Layout CSS](https://golden-layout.com/), which allows for the creation of tabs that can be moved around. Due to the movable tabs this Template is a little different than the others. The sidebar works similarly to the other templates, but to have your displays render in different tabs, we have to make separate calls to `.main.append()`. Here is an example of how you can set up a display using this template:" + ], + "metadata": {} }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], "source": [ "golden = pn.template.GoldenTemplate(title='Golden Template')\n", "\n", @@ -91,29 +89,31 @@ ")\n", "\n", "golden.servable();" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ "

GoldenTemplate with DefaultTheme

\n", "\n", "
\n", "

GoldenTemplate with DarkTheme

\n", "" - ] + ], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ "The app can be displayed within the notebook by using `.servable()`, or rendered in another tab by replacing it with `.show()`. \n", "\n", "Themes can be added using the optional keyword argument `theme`. Each template comes with a DarkTheme and a DefaultTheme, which can be set `GoldenTemplate(theme=DarkTheme)`. If no theme is set, then DefaultTheme will be applied.\n", "\n", "It should be noted that Templates may not render correctly in a notebook, and for the best performance the should ideally be deployed to a server." - ] + ], + "metadata": {} } ], "metadata": { @@ -137,4 +137,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} +} \ No newline at end of file diff --git a/examples/reference/templates/Material.ipynb b/examples/reference/templates/Material.ipynb index 0457479160..846a38cdc1 100644 --- a/examples/reference/templates/Material.ipynb +++ b/examples/reference/templates/Material.ipynb @@ -17,14 +17,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "For a large variety of use cases we do not need complete control over the exact layout of each individual component on the page, as could be achieved with a [custom template](../../user_guide/Templates.ipynb), we just want to achieve a more polished look and feel. For these cases Panel ships with a number of default templates, which are defined by declaring three main content areas on the page, which can be populated as desired:\n", + "For a large variety of use cases we do not need complete control over the exact layout of each individual component on the page, as could be achieved with a [custom template](../../user_guide/Templates.ipynb), we just want to achieve a more polished look and feel. For these cases Panel ships with a number of default templates, which are defined by declaring four main content areas on the page, which can be populated as desired:\n", "\n", "* **`header`**: The header area of the HTML page\n", "* **`sidebar`**: A collapsible sidebar\n", "* **`main`**: The main area of the application\n", "* **`modal`**: A modal area which can be opened and closed from Python\n", "\n", - "These three areas behave very similarly to other Panel layout components and have list-like semantics. This means we can easily append new components into these areas. Unlike other layout components however, the contents of the areas is fixed once rendered. If you need a dynamic layout you should therefore insert a regular Panel layout component (e.g. a `Column` or `Row`) and modify it in place once added to one of the content areas. \n", + "These four areas behave very similarly to other Panel layout components and have list-like semantics. This means we can easily append new components into these areas. Unlike other layout components however, the contents of the areas is fixed once rendered. If you need a dynamic layout you should therefore insert a regular Panel layout component (e.g. a `Column` or `Row`) and modify it in place once added to one of the content areas. \n", "\n", "Templates can allow for us to quickly and easily create web apps for displaying our data. Panel comes with a default Template, and includes multiple Templates that extend the default which add some customization for a better display.\n", "\n", diff --git a/examples/reference/templates/Vanilla.ipynb b/examples/reference/templates/Vanilla.ipynb index c7e806c710..c78fdba154 100644 --- a/examples/reference/templates/Vanilla.ipynb +++ b/examples/reference/templates/Vanilla.ipynb @@ -17,14 +17,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "For a large variety of use cases we do not need complete control over the exact layout of each individual component on the page, as could be achieved with a [custom template](../../user_guide/Templates.ipynb), we just want to achieve a more polished look and feel. For these cases Panel ships with a number of default templates, which are defined by declaring three main content areas on the page, which can be populated as desired:\n", + "For a large variety of use cases we do not need complete control over the exact layout of each individual component on the page, as could be achieved with a [custom template](../../user_guide/Templates.ipynb), we just want to achieve a more polished look and feel. For these cases Panel ships with a number of default templates, which are defined by declaring four main content areas on the page, which can be populated as desired:\n", "\n", "* **`header`**: The header area of the HTML page\n", "* **`sidebar`**: A collapsible sidebar\n", "* **`main`**: The main area of the application\n", "* **`modal`**: A modal area which can be opened and closed from Python\n", "\n", - "These three areas behave very similarly to other Panel layout components and have list-like semantics. This means we can easily append new components into these areas. Unlike other layout components however, the contents of the areas is fixed once rendered. If you need a dynamic layout you should therefore insert a regular Panel layout component (e.g. a `Column` or `Row`) and modify it in place once added to one of the content areas. \n", + "These four areas behave very similarly to other Panel layout components and have list-like semantics. This means we can easily append new components into these areas. Unlike other layout components however, the contents of the areas is fixed once rendered. If you need a dynamic layout you should therefore insert a regular Panel layout component (e.g. a `Column` or `Row`) and modify it in place once added to one of the content areas. \n", "\n", "Templates can allow for us to quickly and easily create web apps for displaying our data. Panel comes with a default Template, and includes multiple Templates that extend the default which add some customization for a better display.\n", "\n", diff --git a/examples/user_guide/Templates.ipynb b/examples/user_guide/Templates.ipynb index d1a84d2ebc..dc30250e37 100644 --- a/examples/user_guide/Templates.ipynb +++ b/examples/user_guide/Templates.ipynb @@ -2,63 +2,64 @@ "cells": [ { "cell_type": "markdown", - "metadata": {}, "source": [ "When deploying a Panel app or dashboard as a Bokeh application, it is rendered into a default template that serves the JS and CSS resources as well as the actual Panel object being shown. However, it is often desirable to customize the layout of the deployed app, or even to embed multiple separate panels into an app. The ``Template`` component in Panel allows customizing this default template, including the ability to rendering multiple components in a single document easily.\n", "\n", "## What is a template?\n", "\n", "A template is defined using the [Jinja2](http://jinja.pocoo.org/docs/) templating language, which makes it straightforward to extend the default template in various ways or even replace it entirely. However most users can avoid modifying the jinja2 template directly by using one of the default templates shipped with Panel itself." - ] + ], + "metadata": {} }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], "source": [ "import panel as pn\n", "import numpy as np\n", "import holoviews as hv\n", "\n", "pn.extension(sizing_mode='stretch_width')" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ "## Using default templates\n", "\n", - "For a large variety of use cases we do not need complete control over the exact layout of each individual component on the page we just want to achieve a more polished look and feel. For these cases Panel ships with a number of default templates, which are defined by declaring four main content areas on the page, which can be populated as desired:\n", + "For a large variety of use cases we do not need complete control over the exact layout of each individual component on the page, instead we just want to achieve a more polished look and feel. For these cases Panel ships with a number of default templates, which are defined by declaring four main content areas on the page, which can be populated as desired:\n", "\n", "* **`header`**: The header area of the HTML page\n", "* **`sidebar`**: A collapsible sidebar\n", "* **`main`**: The main area of the application\n", - "* **`modal`**: A modal that can be toggled opened and closed with `.open_modal()` and `.close_modal()` methods\n", + "* **`modal`**: A modal, i.e. a dialog box/popup window\n", "\n", - "These three areas behave very similarly to other Panel layout components and have list-like semantics. This means we can easily append new components into these areas. Unlike other layout components however, the contents of the areas is fixed once rendered. If you need a dynamic layout you should therefore insert a regular Panel layout component (e.g. a `Column` or `Row`) and modify it in place once added to one of the content areas. \n" - ] + "These four areas behave very similarly to other Panel layout components and have list-like semantics. This means we can easily append new components into these areas. Unlike other layout components however, the contents of the areas is fixed once rendered. If you need a dynamic layout you should therefore insert a regular Panel layout component (e.g. a `Column` or `Row`) and modify it in place once added to one of the content areas. \n", + "\n", + "" + ], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ "### Supported templates\n", "\n", "Panel ships with a number of these default themes built on different CSS frameworks:\n", " \n", - "* `MaterialTemplate`: Built on [Material Components for the web](https://material.io/develop/web/)\n", - "* `BootstrapTemplate`: Built on [Bootstrap v4](https://getbootstrap.com/docs/4.0/getting-started/introduction/)\n", - "* `VanillaTemplate`: Built using pure CSS without relying on any specific framework\n", - "* `FastListTemplate`: Built on the [Fast UI](https://fast.design/) framework using a list-like API\n", - "* `FastGridTemplate`: Built on the [Fast UI](https://fast.design/) framework using grid-like API\n", - "* `GoldenTemplate`: Built on the [Golden Layout](https://golden-layout.com/) framework" - ] + "* **[``MaterialTemplate``](../reference/templates/Material.ipynb)**: Built on [Material Components for the web](https://material.io/develop/web/)\n", + "* **[``BootstrapTemplate``](../reference/templates/Bootstrap.ipynb)**: Built on [Bootstrap v4](https://getbootstrap.com/docs/4.0/getting-started/introduction/)\n", + "* **[``VanillaTemplate``](../reference/templates/Vanilla.ipynb)**: Built using pure CSS without relying on any specific framework\n", + "* **[``FastListTemplate``](../reference/templates/FastListTemplate.ipynb)**: Built on the [Fast UI](https://fast.design/) framework using a list-like API\n", + "* **[``FastGridTemplate``](../reference/templates/FastGridTemplate.ipynb)**: Built on the [Fast UI](https://fast.design/) framework using grid-like API\n", + "* **[``GoldenTemplate``](../reference/templates/GoldenLayout.ipynb)**: Built on the [Golden Layout](https://golden-layout.com/) framework" + ], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ "### Using templates\n", "\n", @@ -67,13 +68,12 @@ "#### Explicit constructor\n", "\n", "The explicit way to use templates is to instantiate them directly and adding components to the different parts of the template directly. Let us construct a very simple app containing two plots in the `main` area and two widgets in the sidebar based on the `BootstrapTemplate` class:" - ] + ], + "metadata": {} }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], "source": [ "bootstrap = pn.template.BootstrapTemplate(title='Bootstrap Template')\n", "\n", @@ -100,11 +100,12 @@ " pn.Card(hv.DynamicMap(cosine), title='Cosine')\n", " )\n", ")" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "
\n", @@ -113,11 +114,11 @@ "
\n", "\n", "A `Template` can be served or displayed just like any other Panel component, i.e. using `.servable()` or `.show()`." - ] + ], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ "### Global template\n", "\n", @@ -144,40 +145,71 @@ " pn.Card(hv.DynamicMap(cosine), title='Cosine')\n", ").servable(area='main') # Note 'main' is the default\n", "```" - ] + ], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ - "### Theming\n", + "### Modal\n", "\n", - "Default template classes provide a unified approach to theming, which currently allow specifying custom CSS and the Bokeh `Theme` to apply to the `Template`. The way it is implemented a user declares a generic `Theme` class and the `Template` loads the specific implementation for a particular `Template`. To make this more concrete, by default a Template uses the `DefaultTheme`, but then uses the `find_theme` method to look up the implementation of that theme for the Template being used:" - ] + "A modal can be toggled opened and closed with `.open_modal()` and `.close_modal()` methods. For example, a temporary *About* modal could be added to the previous app with:" + ], + "metadata": {} }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "source": [ + "import time\n", + "\n", + "# Callback that will be called when the About button is clicked\n", + "def about_callback(event):\n", + " bootstrap.open_modal()\n", + " time.sleep(10)\n", + " bootstrap.close_modal()\n", + "\n", + "# Create, link and add the button to the sidebar\n", + "btn = pn.widgets.Button(name=\"About\")\n", + "btn.on_click(about_callback)\n", + "bootstrap.sidebar.append(btn)\n", + "\n", + "# Add some content to the modal\n", + "bootstrap.modal.append(\"# About...\")" + ], "outputs": [], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "### Theming\n", + "\n", + "Default template classes provide a unified approach to theming, which currently allow specifying custom CSS and the Bokeh `Theme` to apply to the `Template`. The way it is implemented a user declares a generic `Theme` class to use (e.g. `DarkTheme`) which loads the specific theme implementation (e.g. `MaterialDarkTheme`) for a particular `Template` (e.g `MaterialTemplate`). To make this more concrete, by default a Template uses the `DefaultTheme`, but then uses the `find_theme` method to look up the implementation of that theme for the Template being used:" + ], + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": null, "source": [ "from panel.template import DefaultTheme\n", "\n", "DefaultTheme.find_theme(pn.template.MaterialTemplate)" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ "To implement your own theme you should therefore declare a generic class for use by the enduser and a specific implementation for all the themes that should be supported, e.g. here is an example of what the definition of a dark theme might look like:" - ] + ], + "metadata": {} }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], "source": [ "import param\n", "\n", @@ -197,20 +229,20 @@ " \n", " # This tells Panel to use this implementation\n", " _template = pn.template.MaterialTemplate" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ "To apply the theme we now merely have to provide the generic `DarkTheme` class to the Template (we will import the `DarkTheme` that ships with panel here:" - ] + ], + "metadata": {} }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], "source": [ "from panel.template import DarkTheme\n", "\n", @@ -225,22 +257,23 @@ " pn.Card(hv.DynamicMap(cosine), title='Cosine')\n", " )\n", ")" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "
\n", "\n", " Dark Theme: The MaterialTemplate with a DarkTheme applied\n", "
" - ] + ], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ "## Using custom templates\n", "\n", @@ -292,13 +325,12 @@ "That said it is usually easiest to simply extend an existing template by overriding certain blocks. To begin with we start by using `{% extends base %}` to declare that we are merely extending an existing template rather than defining a whole new one; otherwise we would have to repeat the entire header sections of the full template to ensure all the appropriate resources are loaded.\n", "\n", "In this case we will extend the postamble block of the header to load some additional resources, and the contents block to redefine how the components will be laid out. Specifically, we will load bootstrap.css in the preamble allowing us to use the bootstrap grid system to lay out the output." - ] + ], + "metadata": {} }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], "source": [ "template = \"\"\"\n", "{% extends base %}\n", @@ -325,22 +357,22 @@ "
\n", "{% endblock %}\n", "\"\"\"" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ "If you look closely we defined two different roots in the template using the `embed` macro. In order to be able to render the template we now have to first construct the `pn.Template` object with the template HTML and then populate the template with the two required roots, in this case `'A'` and `'B'` by using the `add_panel` method. If either of the roots is not defined the app is invalid and will fail to launch. The app will also fail to launch if any panels are added that are not referenced in the template.\n", "\n", "Additionally we have also declared a new `app_title` variable in the template, which we can populate by using the `add_variable` method:" - ] + ], + "metadata": {} }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], "source": [ "tmpl = pn.Template(template)\n", "\n", @@ -350,20 +382,20 @@ "tmpl.add_panel('B', hv.Curve([1, 2, 3]))\n", "\n", "tmpl" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ "Embedding a different CSS framework (like Bootstrap) in the notebook can have undesirable side-effects so a `Template` may also be given a separate `nb_template` that will be used when rendering inside the notebook:" - ] + ], + "metadata": {} }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], "source": [ "nb_template = \"\"\"\n", "{% extends base %}\n", @@ -391,22 +423,22 @@ "tmpl.add_panel('B', hv.Curve([1, 2, 3]))\n", "\n", "tmpl" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ "### Loading template from file\n", "\n", "If the template is larger it is often cleaner to define it in a separate file. You can either read it in as a string, or use the official loading mechanism available for Jinja2 templates by defining a `Environment` along with a `loader`." - ] + ], + "metadata": {} }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], "source": [ "from jinja2 import Environment, FileSystemLoader\n", "\n", @@ -418,7 +450,9 @@ "tmpl.add_panel('A', hv.Curve([1, 2, 3]))\n", "tmpl.add_panel('B', hv.Curve([1, 2, 3]))\n", "tmpl.servable()" - ] + ], + "outputs": [], + "metadata": {} } ], "metadata": { @@ -449,4 +483,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} +} \ No newline at end of file