Skip to content

Commit

Permalink
Adds turbo_refreshes_with template tag
Browse files Browse the repository at this point in the history
For support for morphing coming in Turbo 8, hotwired/turbo#1019

Duplicates the Rails turbo_refreshes_with template helper.

Updated docs and helper
  • Loading branch information
chrisgrande committed Jan 30, 2024
1 parent a657d87 commit c690005
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
21 changes: 21 additions & 0 deletions docs/source/morphing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
## turbo_refreshes_with

This template tag generates HTML meta tags for Turbo Drive to control the refresh method and scroll behavior in Turbo 8.0+ ([currently in beta](https://github.com/hotwired/turbo/releases/tag/v8.0.0-beta.4)).

### Parameters

- `method` (optional, default: `'replace'`): Specifies the refresh method. Must be one of `'replace'` or `'morph'`.
- `scroll` (optional, default: `'reset'`): Specifies the scroll behavior. Must be one of `'reset'` or `'preserve'`.

### Behavior

This tag creates HTML meta tags defining the Turbo Frames' refresh method and scroll behavior based on the provided parameters. If the provided parameters are not within the valid options, a `ValidationError` is raised.

### Example Usage

```django
{% load turbo_helper %}
<!-- Generate Turbo Frames refresh meta tags -->
{% turbo_refreshes_with method='replace' scroll='reset' %}
```
18 changes: 18 additions & 0 deletions src/turbo_helper/templatetags/turbo_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
from django import template
from django.db.models.base import Model
from django.template import Node, TemplateSyntaxError
from django.core.exceptions import ValidationError
from django.template.base import token_kwargs
from django.utils.html import format_html

from turbo_helper.renderers import render_turbo_frame, render_turbo_stream_from
from turbo_helper.stream import action_proxy
Expand Down Expand Up @@ -260,3 +262,19 @@ def turbo_stream_from_tag(parser, token):
stream_name_array = [parser.compile_filter(bit) for bit in remaining_bits]

return TurboStreamFromTagNode(stream_name_array)


@register.simple_tag
def turbo_refreshes_with(method='replace', scroll='reset') -> str:
valid_methods = ['replace', 'morph']
valid_scrolls = ['reset', 'preserve']

if method not in valid_methods:
raise ValidationError(f"Invalid refresh option '{method}'")
if scroll not in valid_scrolls:
raise ValidationError(f"Invalid scroll option '{scroll}'")

meta_tags = f'<meta name="turbo-refresh-method" content="{method}">'
meta_tags += f'<meta name="turbo-refresh-scroll" content="{scroll}">'

return format_html(meta_tags)
35 changes: 35 additions & 0 deletions tests/test_tags.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest
from django.core.exceptions import ValidationError
from django.template import Context, Template

from tests.testapp.models import TodoItem
Expand Down Expand Up @@ -169,3 +170,37 @@ def test_dom_id_variable(self):
output
== '<turbo-cable-stream-source channel="TurboStreamCableChannel" signed-stream-name="test_todo_3:7ZS0MxQWhRTCAnG3olGO9AJKfvos3iaHGoBMBt8ZbSM"></turbo-cable-stream-source>'
)


class TestRefreshesWith:
def test_turbo_refreshes_with_tag(self):
template = """
{% load turbo_helper %}
{% turbo_refreshes_with method='replace' scroll='reset' %}
"""

output = render(template, {}).strip()

expected_method_tag = '<meta name="turbo-refresh-method" content="replace">'
expected_scroll_tag = '<meta name="turbo-refresh-scroll" content="reset">'

assert expected_method_tag in output
assert expected_scroll_tag in output

def test_invalid_options(self):
with pytest.raises(ValidationError):
template = """
{% load turbo_helper %}
{% turbo_refreshes_with method='invalid' scroll='reset' %}
"""
output = render(template, {}).strip()

with pytest.raises(ValidationError):
template = """
{% load turbo_helper %}
{% turbo_refreshes_with method='replace' scroll='invalid' %}
"""
output = render(template, {}).strip()

0 comments on commit c690005

Please sign in to comment.