Add slots to components that can be filled when using component.

This commit is contained in:
Emil Stenström 2020-06-06 09:11:27 +02:00
parent f6d2c5e003
commit d1405dda13
6 changed files with 316 additions and 13 deletions

View file

@ -1,5 +1,9 @@
from inspect import getfullargspec
from django.forms.widgets import MediaDefiningClass
from django.template.loader import render_to_string
from django.template import Context
from django.template.base import NodeList, TokenType, TextNode
from django.template.loader import get_template
from six import with_metaclass
# Allow "component.AlreadyRegistered" instead of having to import these everywhere
@ -16,9 +20,44 @@ class Component(with_metaclass(MediaDefiningClass)):
def render_dependencies(self):
return self.media.render()
def render(self, *args, **kwargs):
context = self.context(*args, **kwargs)
return render_to_string(self.template(context), context)
def slots_in_template(self, template):
nodelist = NodeList()
for node in template.template.nodelist:
if (
node.token.token_type == TokenType.BLOCK
and node.token.split_contents()[0] == "slot"
):
nodelist.append(node)
return nodelist
def render(self, slots_filled=None, *args, **kwargs):
slots_filled = slots_filled or []
context_args_variables = getfullargspec(self.context).args[1:]
context_args = {key: kwargs[key] for key in context_args_variables if key in kwargs}
context = self.context(**context_args)
template = get_template(self.template(context))
slots_in_template = self.slots_in_template(template)
if slots_in_template:
valid_slot_names = set([slot.name for slot in slots_in_template])
nodelist = NodeList()
for node in template.template.nodelist:
if (
node.token.token_type == TokenType.BLOCK
and node.token.split_contents()[0] == "slot"
):
if node.name in valid_slot_names and node.name in slots_filled:
nodelist.append(TextNode(slots_filled[node.name]))
else:
for node in node.nodelist:
nodelist.append(node)
else:
nodelist.append(node)
return nodelist.render(Context(context))
return template.render(context)
class Media:
css = {}