Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Scoped slots + Updated docs #495

Merged
merged 16 commits into from
May 23, 2024

Conversation

JuroOravec
Copy link
Collaborator

@JuroOravec JuroOravec commented May 13, 2024

Implementation may still change based on feedback. This MR is now ready for review, it adds "scoped slot" feature as per #494 (comment).

I also moved the README sections around a bit, and added a view missing sections. See the screenshot in #495 (comment) and other comments below.

Closes #494

@@ -433,20 +442,3 @@ def render(self, context: Context) -> str:

trace_msg("RENDR", "COMP", self.name_fexp, self.component_id, "...Done!")
return output


def safe_resolve_list(args: List[FilterExpression], context: Context) -> List:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved functions that work with FilterExpression into file expression.py

return HtmlAttrsNode(attributes, default_attrs, append_attrs)


def is_whitespace_node(node: Node) -> bool:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These three is_whitespace_node, is_whitespace_token and is_block_tag_token weren't being used. Actually, even in the MR that introduced them didn't use them. Since it's not documented, I assume it's not part of the public API.

@@ -393,7 +469,3 @@ def _get_positional_param(

def is_wrapped_in_quotes(s: str) -> bool:
return s.startswith(('"', "'")) and s[0] == s[-1]


def strip_quotes(s: str) -> str:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of stripping quotes outselves, I used FilterExpression.resolve() to do that for us here https://github.com/EmilStenstrom/django-components/pull/495/files#diff-7345171ed38e1dd2e4b8199b65a2fd082323bdb331ff0ef0dc0dd3bd43f111aeR345

@@ -237,19 +237,43 @@ class Calendar(component.Component):

And voilá!! We've created our first component.

## Autodiscovery
## Using single-file components
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the section on "single-file components" and "components as Views" higher up. Might not be easy to see in this diff, and just my personal opinion, but it feels to me that now README flows even a bit better:

  1. installation
  2. creating components (and the different variants thereof)
  3. registering componnt with autodiscovery
  4. using slots and passing data to components (which requires the other component to be registered)
  5. Passing data to components
  6. and them some more niche stuff

Overall the ordering is:

Screenshot 2024-05-13 at 16 19 07

@@ -460,86 +532,88 @@ This is fine too:
{% endcomponent %}
```

### Components as views
### Render fill in multiple places
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this section since it wasn't documented yet.


To be able to access a slot name via `component_vars.is_filled`, the slot name needs to be composed of only alphanumeric characters and underscores (e.g. `this__isvalid_123`).

However, you can still define slots with other special characters. In such case, the slot name in `component_vars.is_filled` is modified to replace all invalid characters into `_`.

So a slot named `"my super-slot :)"` will be available as `component_vars.is_filled.my_super_slot___`.

### Setting Up `ComponentDependencyMiddleware`
### Scoped slots
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added section on scoped slots and moved ComponentDependencyMiddleware further down to its own section on rendering dependencies.

@@ -1175,6 +1349,40 @@ NOTE: `{% csrf_token %}` tags need access to the top-level context, and they wil

Components can also access the outer context in their context methods by accessing the property `outer_context`.

## Rendering JS and CSS dependencies
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the section on middleware here, as I expect that this section will be expanded when we tackle #478

@JuroOravec JuroOravec marked this pull request as ready for review May 16, 2024 06:51
@JuroOravec JuroOravec changed the title WIP: Scoped slots + Updated docs feat: Scoped slots + Updated docs May 16, 2024
@@ -77,6 +81,7 @@ class SlotFill(NamedTuple):
nodelist: NodeList
context_data: Dict
alias: Optional[AliasName]
scope: Optional[ScopeName]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How the feature is implemented is that when we parse slot tags, we note down the kwargs parsed to it, and pass it down. Similarly, when we parse fill tags, we note down the slot_data variable name, and pass it down. These two then meet when we are rendering a slot, and we assign the slot kwargs to the context under a key set in fill tag.

slot_data value is required to be string literal, e.g. "quoted_string", same as we do for fill name or the as var syntax.

Copy link
Owner

@EmilStenstrom EmilStenstrom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks great. I thought the API was that you set the names of your parameters in the slot tag, but now it takes a data param with a dict instead?

tests/test_templatetags.py Outdated Show resolved Hide resolved
@JuroOravec
Copy link
Collaborator Author

I also added a table of contents to README

Copy link
Owner

@EmilStenstrom EmilStenstrom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really good work on this!

I see no tests with context_behavior="isolated", so I guess that all of them are testing "django"?

@JuroOravec
Copy link
Collaborator Author

@EmilStenstrom

I see no tests with context_behavior="isolated", so I guess that all of them are testing "django"?

No, isolated is still the default. Changing the default involves also changing some tests, as well as documentation. That's why I moved it to a separate issue in #498. And I want to first clean up this one to avoid needlessly complex rebases/merges.

@JuroOravec
Copy link
Collaborator Author

Btw, @EmilStenstrom, what do you think of renaming the kwarg through which we access the data from slot_data to simply data?

When we take also #502 into consideration, then IMO the shorter names would make for a cleaner API.

Consider:

{% fill "my_slot" data="slot_data" default="slot_default" %}

vs

{% fill "my_slot" slot_data="slot_data" slot_default="slot_default" %}

@EmilStenstrom
Copy link
Owner

@JuroOravec Definitely like the data variable better.

@JuroOravec
Copy link
Collaborator Author

@EmilStenstrom Thanks again for your time and for all the feedback! I've changed slot_data to just data, and I'll go ahead and merge this.

@JuroOravec JuroOravec merged commit b1b66fd into EmilStenstrom:master May 23, 2024
6 checks passed
@JuroOravec JuroOravec deleted the 494-scoped-slots branch May 23, 2024 05:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Scoped slots - Passing data to slots and accessing them in fills
2 participants