diff --git a/src/docs/.gitignore b/src/docs/.gitignore deleted file mode 100644 index 10e83c68..00000000 --- a/src/docs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -reference/ \ No newline at end of file diff --git a/src/docs/reference/api.md b/src/docs/reference/api.md new file mode 100644 index 00000000..6a6d7e47 --- /dev/null +++ b/src/docs/reference/api.md @@ -0,0 +1,105 @@ + + +# API + + +::: django_components.Component + options: + show_if_no_docstring: true + +::: django_components.ComponentFileEntry + options: + show_if_no_docstring: true + +::: django_components.ComponentRegistry + options: + show_if_no_docstring: true + +::: django_components.ComponentVars + options: + show_if_no_docstring: true + +::: django_components.ComponentView + options: + show_if_no_docstring: true + +::: django_components.ComponentsSettings + options: + show_if_no_docstring: true + +::: django_components.ContextBehavior + options: + show_if_no_docstring: true + +::: django_components.EmptyDict + options: + show_if_no_docstring: true + +::: django_components.EmptyTuple + options: + show_if_no_docstring: true + +::: django_components.RegistrySettings + options: + show_if_no_docstring: true + +::: django_components.Slot + options: + show_if_no_docstring: true + +::: django_components.SlotContent + options: + show_if_no_docstring: true + +::: django_components.SlotFunc + options: + show_if_no_docstring: true + +::: django_components.SlotRef + options: + show_if_no_docstring: true + +::: django_components.SlotResult + options: + show_if_no_docstring: true + +::: django_components.TagFormatterABC + options: + show_if_no_docstring: true + +::: django_components.TagResult + options: + show_if_no_docstring: true + +::: django_components.autodiscover + options: + show_if_no_docstring: true + +::: django_components.cached_template + options: + show_if_no_docstring: true + +::: django_components.get_component_dirs + options: + show_if_no_docstring: true + +::: django_components.get_component_files + options: + show_if_no_docstring: true + +::: django_components.import_libraries + options: + show_if_no_docstring: true + +::: django_components.register + options: + show_if_no_docstring: true + +::: django_components.registry + options: + show_if_no_docstring: true + +::: django_components.render_dependencies + options: + show_if_no_docstring: true + diff --git a/src/docs/reference/commands.md b/src/docs/reference/commands.md new file mode 100644 index 00000000..73979ece --- /dev/null +++ b/src/docs/reference/commands.md @@ -0,0 +1,166 @@ + + +# Commands + +These are all the [Django management commands](https://docs.djangoproject.com/en/5.1/ref/django-admin) +that will be added by installing `django_components`: + + +## `upgradecomponent` + +```txt +usage: manage.py upgradecomponent [-h] [--path PATH] [--version] [-v {0,1,2,3}] [--settings SETTINGS] [--pythonpath PYTHONPATH] [--traceback] [--no-color] + [--force-color] [--skip-checks] + +``` + + + +See source code + + + +Updates component and component_block tags to the new syntax + +**Options:** + +- `-h`, `--help` + - show this help message and exit +- `--path PATH` + - Path to search for components +- `--version` + - Show program's version number and exit. +- `-v {0,1,2,3}`, `--verbosity {0,1,2,3}` + - Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output +- `--settings SETTINGS` + - The Python path to a settings module, e.g. "myproject.settings.main". If this isn't provided, the DJANGO_SETTINGS_MODULE environment variable will be used. +- `--pythonpath PYTHONPATH` + - A directory to add to the Python path, e.g. "/home/djangoprojects/myproject". +- `--traceback` + - Raise on CommandError exceptions. +- `--no-color` + - Don't colorize the command output. +- `--force-color` + - Force colorization of the command output. +- `--skip-checks` + - Skip system checks. + + + + + +## `startcomponent` + +```txt +usage: manage.py startcomponent [-h] [--path PATH] [--js JS] [--css CSS] [--template TEMPLATE] [--force] [--verbose] [--dry-run] [--version] [-v {0,1,2,3}] + [--settings SETTINGS] [--pythonpath PYTHONPATH] [--traceback] [--no-color] [--force-color] [--skip-checks] + name + +``` + + + +See source code + + + +Create a new django component. + +**Positional Arguments:** + +- `name` + - The name of the component to create. This is a required argument. + +**Options:** + +- `-h`, `--help` + - show this help message and exit +- `--path PATH` + - The path to the component's directory. This is an optional argument. If not provided, the command will use the `COMPONENTS.dirs` setting from your Django settings. +- `--js JS` + - The name of the JavaScript file. This is an optional argument. The default value is `script.js`. +- `--css CSS` + - The name of the CSS file. This is an optional argument. The default value is `style.css`. +- `--template TEMPLATE` + - The name of the template file. This is an optional argument. The default value is `template.html`. +- `--force` + - This option allows you to overwrite existing files if they exist. This is an optional argument. +- `--verbose` + - This option allows the command to print additional information during component creation. This is an optional argument. +- `--dry-run` + - This option allows you to simulate component creation without actually creating any files. This is an optional argument. The default value is `False`. +- `--version` + - Show program's version number and exit. +- `-v {0,1,2,3}`, `--verbosity {0,1,2,3}` + - Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output +- `--settings SETTINGS` + - The Python path to a settings module, e.g. "myproject.settings.main". If this isn't provided, the DJANGO_SETTINGS_MODULE environment variable will be used. +- `--pythonpath PYTHONPATH` + - A directory to add to the Python path, e.g. "/home/djangoprojects/myproject". +- `--traceback` + - Raise on CommandError exceptions. +- `--no-color` + - Don't colorize the command output. +- `--force-color` + - Force colorization of the command output. +- `--skip-checks` + - Skip system checks. + + + + +### Management Command Usage + +To use the command, run the following command in your terminal: + +```bash +python manage.py startcomponent --path --js --css --template --force --verbose --dry-run +``` + +Replace ``, ``, ``, ``, and `` with your desired values. + +### Management Command Examples + +Here are some examples of how you can use the command: + +#### Creating a Component with Default Settings + +To create a component with the default settings, you only need to provide the name of the component: + +```bash +python manage.py startcomponent my_component +``` + +This will create a new component named `my_component` in the `components` directory of your Django project. The JavaScript, CSS, and template files will be named `script.js`, `style.css`, and `template.html`, respectively. + +#### Creating a Component with Custom Settings + +You can also create a component with custom settings by providing additional arguments: + +```bash +python manage.py startcomponent new_component --path my_components --js my_script.js --css my_style.css --template my_template.html +``` + +This will create a new component named `new_component` in the `my_components` directory. The JavaScript, CSS, and template files will be named `my_script.js`, `my_style.css`, and `my_template.html`, respectively. + +#### Overwriting an Existing Component + +If you want to overwrite an existing component, you can use the `--force` option: + +```bash +python manage.py startcomponent my_component --force +``` + +This will overwrite the existing `my_component` if it exists. + +#### Simulating Component Creation + +If you want to simulate the creation of a component without actually creating any files, you can use the `--dry-run` option: + +```bash +python manage.py startcomponent my_component --dry-run +``` + +This will simulate the creation of `my_component` without creating any files. + + diff --git a/src/docs/reference/components.md b/src/docs/reference/components.md new file mode 100644 index 00000000..bba6868b --- /dev/null +++ b/src/docs/reference/components.md @@ -0,0 +1,15 @@ + + +# Components + +These are the components provided by django_components. + + +::: django_components.components.dynamic.DynamicComponent + options: + inherited_members: false + show_root_heading: true + show_signature: false + separate_signature: false + members: false + diff --git a/src/docs/reference/exceptions.md b/src/docs/reference/exceptions.md new file mode 100644 index 00000000..78c2ac43 --- /dev/null +++ b/src/docs/reference/exceptions.md @@ -0,0 +1,17 @@ + + +# Exceptions + + +::: django_components.AlreadyRegistered + options: + show_if_no_docstring: true + +::: django_components.NotRegistered + options: + show_if_no_docstring: true + +::: django_components.TagProtectedError + options: + show_if_no_docstring: true + diff --git a/src/docs/reference/middlewares.md b/src/docs/reference/middlewares.md new file mode 100644 index 00000000..08c2b63b --- /dev/null +++ b/src/docs/reference/middlewares.md @@ -0,0 +1,16 @@ + + +# Middlewares + + +::: django_components.dependencies.ComponentDependencyMiddleware + options: + inherited_members: false + show_root_heading: true + show_signature: false + separate_signature: false + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + diff --git a/src/docs/reference/settings.md b/src/docs/reference/settings.md new file mode 100644 index 00000000..8dfa16a9 --- /dev/null +++ b/src/docs/reference/settings.md @@ -0,0 +1,205 @@ + + +# Settings + +You can configure django_components with a global `COMPONENTS` variable in your Django settings file, e.g. `settings.py`. +By default you don't need it set, there are resonable [defaults](#settings-defaults). + +To configure the settings you can instantiate [`ComponentsSettings`](../api#django_components.ComponentsSettings) +for validation and type hints. Or, for backwards compatibility, you can also use plain dictionary: + +```python +# settings.py +from django_components import ComponentsSettings + +COMPONENTS = ComponentsSettings( + autodiscover=True, + ... +) + +# or + +COMPONENTS = { + "autodiscover": True, + ... +} +``` + + +### Settings defaults + +Here's overview of all available settings and their defaults: + +```py +defaults = ComponentsSettings( + autodiscover=True, + context_behavior=ContextBehavior.DJANGO.value, # "django" | "isolated" + # Root-level "components" dirs, e.g. `/path/to/proj/components/` + dirs=[Path(settings.BASE_DIR) / "components"], + # App-level "components" dirs, e.g. `[app]/components/` + app_dirs=["components"], + dynamic_component_name="dynamic", + libraries=[], # E.g. ["mysite.components.forms", ...] + multiline_tags=True, + reload_on_file_change=False, + static_files_allowed=[ + ".css", + ".js", ".jsx", ".ts", ".tsx", + # Images + ".apng", ".png", ".avif", ".gif", ".jpg", + ".jpeg", ".jfif", ".pjpeg", ".pjp", ".svg", + ".webp", ".bmp", ".ico", ".cur", ".tif", ".tiff", + # Fonts + ".eot", ".ttf", ".woff", ".otf", ".svg", + ], + static_files_forbidden=[ + # See https://marketplace.visualstudio.com/items?itemName=junstyle.vscode-django-support + ".html", ".django", ".dj", ".tpl", + # Python files + ".py", ".pyc", + ], + tag_formatter="django_components.component_formatter", + template_cache_size=128, +) +``` + +::: django_components.app_settings.ComponentsSettings.app_dirs + options: + show_root_heading: true + show_signature: true + separate_signature: true + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + +::: django_components.app_settings.ComponentsSettings.autodiscover + options: + show_root_heading: true + show_signature: true + separate_signature: true + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + +::: django_components.app_settings.ComponentsSettings.context_behavior + options: + show_root_heading: true + show_signature: true + separate_signature: true + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + +::: django_components.app_settings.ComponentsSettings.dirs + options: + show_root_heading: true + show_signature: true + separate_signature: true + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + +::: django_components.app_settings.ComponentsSettings.dynamic_component_name + options: + show_root_heading: true + show_signature: true + separate_signature: true + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + +::: django_components.app_settings.ComponentsSettings.forbidden_static_files + options: + show_root_heading: true + show_signature: true + separate_signature: true + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + +::: django_components.app_settings.ComponentsSettings.libraries + options: + show_root_heading: true + show_signature: true + separate_signature: true + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + +::: django_components.app_settings.ComponentsSettings.multiline_tags + options: + show_root_heading: true + show_signature: true + separate_signature: true + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + +::: django_components.app_settings.ComponentsSettings.reload_on_file_change + options: + show_root_heading: true + show_signature: true + separate_signature: true + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + +::: django_components.app_settings.ComponentsSettings.reload_on_template_change + options: + show_root_heading: true + show_signature: true + separate_signature: true + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + +::: django_components.app_settings.ComponentsSettings.static_files_allowed + options: + show_root_heading: true + show_signature: true + separate_signature: true + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + +::: django_components.app_settings.ComponentsSettings.static_files_forbidden + options: + show_root_heading: true + show_signature: true + separate_signature: true + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + +::: django_components.app_settings.ComponentsSettings.tag_formatter + options: + show_root_heading: true + show_signature: true + separate_signature: true + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + +::: django_components.app_settings.ComponentsSettings.template_cache_size + options: + show_root_heading: true + show_signature: true + separate_signature: true + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + diff --git a/src/docs/reference/tag_formatters.md b/src/docs/reference/tag_formatters.md new file mode 100644 index 00000000..9cdc2b16 --- /dev/null +++ b/src/docs/reference/tag_formatters.md @@ -0,0 +1,40 @@ + + +# Tag Formatters + +[Tag formatters](../../concepts/advanced/tag_formatter) allow you to change the syntax for calling components from within +the Django templates. + +Tag formatter are set via the [tag_formatter](../settings#django_components.app_settings.ComponentsSettings.tag_formatter) +setting. + + +### Available tag formatters + +- `django_components.component_formatter` for [ComponentFormatter](#django_components.tag_formatter.ComponentFormatter) + +- `django_components.component_shorthand_formatter` for [ShorthandComponentFormatter](#django_components.tag_formatter.ShorthandComponentFormatter) +::: django_components.tag_formatter.ComponentFormatter + options: + inherited_members: false + show_root_heading: true + show_signature: false + separate_signature: false + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + members: false + +::: django_components.tag_formatter.ShorthandComponentFormatter + options: + inherited_members: false + show_root_heading: true + show_signature: false + separate_signature: false + show_symbol_type_heading: false + show_symbol_type_toc: false + show_if_no_docstring: true + show_labels: false + members: false + diff --git a/src/docs/reference/template_tags.md b/src/docs/reference/template_tags.md new file mode 100644 index 00000000..933624f7 --- /dev/null +++ b/src/docs/reference/template_tags.md @@ -0,0 +1,543 @@ + + +# Template tags + + +All following template tags are defined in + +`django_components.templatetags.component_tags` + +Import as +```django +{% load component_tags %} +``` + +## component + +```django +{% component [arg, ...] **kwargs [only] %} +{% endcomponent %} +``` + + + +See source code + + + +Renders one of the components that was previously registered with +[`@register()`](./api.md#django_components.register) +decorator. + +**Args:** + +- `name` (str, required): Registered name of the component to render +- All other args and kwargs are defined based on the component itself. + +If you defined a component `"my_table"` + +```python +from django_component import Component, register + +@register("my_table") +class MyTable(Component): + template = """ + + + {% for header in headers %} + + {% endfor %} + + + {% for row in rows %} + + {% for cell in row %} + + {% endfor %} + + {% endfor %} + +
{{ header }}
{{ cell }}
+ """ + + def get_context_data(self, rows: List, headers: List): + return { + "rows": rows, + "headers": headers, + } +``` + +Then you can render this component by referring to `MyTable` via its +registered name `"my_table"`: + +```django +{% component "my_table" rows=rows headers=headers ... / %} +``` + +### Component input + +Positional and keyword arguments can be literals or template variables. + +The component name must be a single- or double-quotes string and must +be either: + +- The first positional argument after `component`: + + ```django + {% component "my_table" rows=rows headers=headers ... / %} + ``` + +- Passed as kwarg `name`: + + ```django + {% component rows=rows headers=headers name="my_table" ... / %} + ``` + +### Inserting into slots + +If the component defined any [slots](../concepts/fundamentals/slots.md), you can +pass in the content to be placed inside those slots by inserting [`{% fill %}`](#fill) tags, +directly within the `{% component %}` tag: + +```django +{% component "my_table" rows=rows headers=headers ... / %} + {% fill "pagination" %} + < 1 | 2 | 3 > + {% endfill %} +{% endcomponent %} +``` + +### Isolating components + +By default, components behave similarly to Django's +[`{% include %}`](https://docs.djangoproject.com/en/5.1/ref/templates/builtins/#include), +and the template inside the component has access to the variables defined in the outer template. + +You can selectively isolate a component, using the `only` flag, so that the inner template +can access only the data that was explicitly passed to it: + +```django +{% component "name" positional_arg keyword_arg=value ... only %} +``` + +## component_css_dependencies + +```django +{% component_css_dependencies %} +``` + + + +See source code + + + +Marks location where CSS link tags should be rendered after the whole HTML has been generated. + +Generally, this should be inserted into the `` tag of the HTML. + +If the generated HTML does NOT contain any `{% component_css_dependencies %}` tags, CSS links +are by default inserted into the `` tag of the HTML. (See +[JS and CSS output locations](../../concepts/advanced/rendering_js_css/#js-and-css-output-locations)) + +Note that there should be only one `{% component_css_dependencies %}` for the whole HTML document. +If you insert this tag multiple times, ALL CSS links will be duplicately inserted into ALL these places. + +## component_js_dependencies + +```django +{% component_js_dependencies %} +``` + + + +See source code + + + +Marks location where JS link tags should be rendered after the whole HTML has been generated. + +Generally, this should be inserted at the end of the `` tag of the HTML. + +If the generated HTML does NOT contain any `{% component_js_dependencies %}` tags, JS scripts +are by default inserted at the end of the `` tag of the HTML. (See +[JS and CSS output locations](../../concepts/advanced/rendering_js_css/#js-and-css-output-locations)) + +Note that there should be only one `{% component_js_dependencies %}` for the whole HTML document. +If you insert this tag multiple times, ALL JS scripts will be duplicately inserted into ALL these places. + +## fill + +```django +{% fill name data=None default=None %} +{% endfill %} +``` + + + +See source code + + + +Use this tag to insert content into component's slots. + +`{% fill %}` tag may be used only within a `{% component %}..{% endcomponent %}` block. +Runtime checks should prohibit other usages. + +**Args:** + +- `name` (str, required): Name of the slot to insert this content into. Use `"default"` for + the default slot. +- `default` (str, optional): This argument allows you to access the original content of the slot + under the specified variable name. See + [Accessing original content of slots](../../concepts/fundamentals/slots#accessing-original-content-of-slots) +- `data` (str, optional): This argument allows you to access the data passed to the slot + under the specified variable name. See [Scoped slots](../../concepts/fundamentals/slots#scoped-slots) + +**Examples:** + +Basic usage: +```django +{% component "my_table" %} + {% fill "pagination" %} + < 1 | 2 | 3 > + {% endfill %} +{% endcomponent %} +``` + +### Accessing slot's default content with the `default` kwarg + +```django +{# my_table.html #} + + ... + {% slot "pagination" %} + < 1 | 2 | 3 > + {% endslot %} +
+``` + +```django +{% component "my_table" %} + {% fill "pagination" default="default_pag" %} +
+ {{ default_pag }} +
+ {% endfill %} +{% endcomponent %} +``` + +### Accessing slot's data with the `data` kwarg + +```django +{# my_table.html #} + + ... + {% slot "pagination" pages=pages %} + < 1 | 2 | 3 > + {% endslot %} +
+``` + +```django +{% component "my_table" %} + {% fill "pagination" data="slot_data" %} + {% for page in slot_data.pages %} + + {{ page.index }} + + {% endfor %} + {% endfill %} +{% endcomponent %} +``` + +### Accessing slot data and default content on the default slot + +To access slot data and the default slot content on the default slot, +use `{% fill %}` with `name` set to `"default"`: + +```django +{% component "button" %} + {% fill name="default" data="slot_data" default="default_slot" %} + You clicked me {{ slot_data.count }} times! + {{ default_slot }} + {% endfill %} +{% endcomponent %} +``` + +## html_attrs + +```django +{% html_attrs attrs=None defaults=None **kwargs %} +``` + + + +See source code + + + +Generate HTML attributes (`key="value"`), combining data from multiple sources, +whether its template variables or static text. + +It is designed to easily merge HTML attributes passed from outside with the internal. +See how to in [Passing HTML attributes to components](../../guides/howto/passing_html_attrs/). + +**Args:** + +- `attrs` (dict, optional): Optional dictionary that holds HTML attributes. On conflict, overrides + values in the `default` dictionary. +- `default` (str, optional): Optional dictionary that holds HTML attributes. On conflict, is overriden + with values in the `attrs` dictionary. +- Any extra kwargs will be appended to the corresponding keys + +The attributes in `attrs` and `defaults` are merged and resulting dict is rendered as HTML attributes +(`key="value"`). + +Extra kwargs (`key=value`) are concatenated to existing keys. So if we have + +```python +attrs = {"class": "my-class"} +``` + +Then + +```django +{% html_attrs attrs class="extra-class" %} +``` + +will result in `class="my-class extra-class"`. + +**Example:** +```django +
+``` + +renders + +```html +
+``` + +**See more usage examples in +[HTML attributes](../../concepts/fundamentals/html_attributes#examples-for-html_attrs).** + +## provide + +```django +{% provide name **kwargs %} +{% endprovide %} +``` + + + +See source code + + + +The "provider" part of the [provide / inject feature](../../concepts/advanced/provide_inject). +Pass kwargs to this tag to define the provider's data. +Any components defined within the `{% provide %}..{% endprovide %}` tags will be able to access this data +with [`Component.inject()`](../api#django_components.Component.inject). + +This is similar to React's [`ContextProvider`](https://react.dev/learn/passing-data-deeply-with-context), +or Vue's [`provide()`](https://vuejs.org/guide/components/provide-inject). + +**Args:** + +- `name` (str, required): Provider name. This is the name you will then use in + [`Component.inject()`](../api#django_components.Component.inject). +- `**kwargs`: Any extra kwargs will be passed as the provided data. + +**Example:** + +Provide the "user_data" in parent component: + +```python +@register("parent") +class Parent(Component): + template = """ +
+ {% provide "user_data" user=user %} + {% component "child" / %} + {% endprovide %} +
+ """ + + def get_context_data(self, user: User): + return { + "user": user, + } +``` + +Since the "child" component is used within the `{% provide %} / {% endprovide %}` tags, +we can request the "user_data" using `Component.inject("user_data")`: + +```python +@register("child") +class Child(Component): + template = """ +
+ User is: {{ user }} +
+ """ + + def get_context_data(self): + user = self.inject("user_data").user + return { + "user": user, + } +``` + +Notice that the keys defined on the `{% provide %}` tag are then accessed as attributes +when accessing them with [`Component.inject()`](../api#django_components.Component.inject). + +✅ Do this +```python +user = self.inject("user_data").user +``` + +❌ Don't do this +```python +user = self.inject("user_data")["user"] +``` + +## slot + +```django +{% slot name **kwargs [default] [required] %} +{% endslot %} +``` + + + +See source code + + + +Slot tag marks a place inside a component where content can be inserted +from outside. + +[Learn more](../../concepts/fundamentals/slots) about using slots. + +This is similar to slots as seen in +[Web components](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot), +[Vue](https://vuejs.org/guide/components/slots.html) +or [React's `children`](https://react.dev/learn/passing-props-to-a-component#passing-jsx-as-children). + +**Args:** + +- `name` (str, required): Registered name of the component to render +- `default`: Optional flag. If there is a default slot, you can pass the component slot content + without using the [`{% fill %}`](#fill) tag. See + [Default slot](../../concepts/fundamentals/slots#default-slot) +- `required`: Optional flag. Will raise an error if a slot is required but not given. +- `**kwargs`: Any extra kwargs will be passed as the slot data. + +**Example:** + +```python +@register("child") +class Child(Component): + template = """ +
+ {% slot "content" default %} + This is shown if not overriden! + {% endslot %} +
+ + """ +``` + +```python +@register("parent") +class Parent(Component): + template = """ +
+ {% component "child" %} + {% fill "content" %} + 🗞️📰 + {% endfill %} + + {% fill "sidebar" %} + 🍷🧉🍾 + {% endfill %} + {% endcomponent %} +
+ """ +``` + +### Passing data to slots + +Any extra kwargs will be considered as slot data, and will be accessible in the [`{% fill %}`](#fill) +tag via fill's `data` kwarg: + +```python +@register("child") +class Child(Component): + template = """ +
+ {# Passing data to the slot #} + {% slot "content" user=user %} + This is shown if not overriden! + {% endslot %} +
+ """ +``` + +```python +@register("parent") +class Parent(Component): + template = """ + {# Parent can access the slot data #} + {% component "child" %} + {% fill "content" data="data" %} +
+ {{ data.user }} +
+ {% endfill %} + {% endcomponent %} + """ +``` + +### Accessing default slot content + +The content between the `{% slot %}..{% endslot %}` tags is the default content that +will be rendered if no fill is given for the slot. + +This default content can then be accessed from within the [`{% fill %}`](#fill) tag using +the fill's `default` kwarg. +This is useful if you need to wrap / prepend / append the original slot's content. + +```python +@register("child") +class Child(Component): + template = """ +
+ {% slot "content" %} + This is default content! + {% endslot %} +
+ """ +``` + +```python +@register("parent") +class Parent(Component): + template = """ + {# Parent can access the slot's default content #} + {% component "child" %} + {% fill "content" default="default" %} + {{ default }} + {% endfill %} + {% endcomponent %} + """ +``` + diff --git a/src/docs/reference/template_vars.md b/src/docs/reference/template_vars.md new file mode 100644 index 00000000..c87a2fd6 --- /dev/null +++ b/src/docs/reference/template_vars.md @@ -0,0 +1,11 @@ + + +# Template variables + +Here is a list of all variables that are automatically available from inside the component's +template and in [`on_render_before` / `on_render_after`](../concepts/advanced/hooks.md##available-hooks) +hooks. + + +::: django_components.component.ComponentVars.is_filled + diff --git a/src/docs/reference/urls.md b/src/docs/reference/urls.md new file mode 100644 index 00000000..3a1d21ce --- /dev/null +++ b/src/docs/reference/urls.md @@ -0,0 +1,25 @@ + + +# URLs + +Below are all the URL patterns that will be added by adding `django_components.urls`. + +See [Installation](../overview/installation.md#adding-support-for-js-and-css) +on how to add these URLs to your Django project. + +Django components already prefixes all URLs with `components/`. So when you are +adding the URLs to `urlpatterns`, you can use an empty string as the first argument: + +```python +from django.urls import include, path + +urlpatterns = [ + ... + path("", include("django_components.urls")), +] +``` + +## List of URLs + + +- `components/cache/./` diff --git a/src/docs/scripts/reference.py b/src/docs/scripts/reference.py index 278dba34..bd85145c 100644 --- a/src/docs/scripts/reference.py +++ b/src/docs/scripts/reference.py @@ -80,7 +80,8 @@ def gen_reference_api(): """ module = import_module("django_components") - preface = (root / "src/docs/templates/reference_api.md").read_text() + preface = "\n\n" + preface += (root / "src/docs/templates/reference_api.md").read_text() out_file = root / "src/docs/reference/api.md" out_file.parent.mkdir(parents=True, exist_ok=True) @@ -116,7 +117,8 @@ def gen_reference_exceptions(): """ module = import_module("django_components") - preface = (root / "src/docs/templates/reference_exceptions.md").read_text() + preface = "\n\n" + preface += (root / "src/docs/templates/reference_exceptions.md").read_text() out_file = root / "src/docs/reference/exceptions.md" out_file.parent.mkdir(parents=True, exist_ok=True) @@ -150,7 +152,8 @@ def gen_reference_components(): """ module = import_module("django_components.components") - preface = (root / "src/docs/templates/reference_components.md").read_text() + preface = "\n\n" + preface += (root / "src/docs/templates/reference_components.md").read_text() out_file = root / "src/docs/reference/components.md" out_file.parent.mkdir(parents=True, exist_ok=True) @@ -199,7 +202,8 @@ def gen_reference_settings(): """ module = import_module("django_components.app_settings") - preface = (root / "src/docs/templates/reference_settings.md").read_text() + preface = "\n\n" + preface += (root / "src/docs/templates/reference_settings.md").read_text() out_file = root / "src/docs/reference/settings.md" out_file.parent.mkdir(parents=True, exist_ok=True) @@ -303,7 +307,8 @@ def gen_reference_middlewares(): """ module = import_module("django_components.middleware") - preface = (root / "src/docs/templates/reference_middlewares.md").read_text() + preface = "\n\n" + preface += (root / "src/docs/templates/reference_middlewares.md").read_text() out_file = root / "src/docs/reference/middlewares.md" out_file.parent.mkdir(parents=True, exist_ok=True) @@ -345,7 +350,8 @@ def gen_reference_tagformatters(): """ module = import_module("django_components") - preface = (root / "src/docs/templates/reference_tagformatters.md").read_text() + preface = "\n\n" + preface += (root / "src/docs/templates/reference_tagformatters.md").read_text() out_file = root / "src/docs/reference/tag_formatters.md" tag_formatter_classes: Dict[str, Type[TagFormatterABC]] = {} @@ -407,7 +413,8 @@ def gen_reference_urls(): """ module = import_module("django_components.urls") - preface = (root / "src/docs/templates/reference_urls.md").read_text() + preface = "\n\n" + preface += (root / "src/docs/templates/reference_urls.md").read_text() out_file = root / "src/docs/reference/urls.md" all_urls = _list_urls(module.urlpatterns) @@ -434,7 +441,8 @@ def gen_reference_commands(): if not p.stem.startswith("_") ] - preface = (root / "src/docs/templates/reference_commands.md").read_text() + preface = "\n\n" + preface += (root / "src/docs/templates/reference_commands.md").read_text() out_file = root / "src/docs/reference/commands.md" out_file.parent.mkdir(parents=True, exist_ok=True) @@ -481,7 +489,8 @@ def gen_reference_templatetags(): (p.stem, f"django_components.templatetags.{p.stem}") for p in tags_files if not p.stem.startswith("_") ] - preface = (root / "src/docs/templates/reference_templatetags.md").read_text() + preface = "\n\n" + preface += (root / "src/docs/templates/reference_templatetags.md").read_text() out_file = root / "src/docs/reference/template_tags.md" out_file.parent.mkdir(parents=True, exist_ok=True) @@ -533,7 +542,8 @@ def gen_reference_templatevars(): Generate documentation for all variables that are available inside the component templates under the `{{ component_vars }}` variable, as defined by `ComponentVars`. """ - preface = (root / "src/docs/templates/reference_templatevars.md").read_text() + preface = "\n\n" + preface += (root / "src/docs/templates/reference_templatevars.md").read_text() out_file = root / "src/docs/reference/template_vars.md" out_file.parent.mkdir(parents=True, exist_ok=True)