-
-
Notifications
You must be signed in to change notification settings - Fork 99
Closed
Labels
Description
Have you ever thought to implement a single file component, similar to vuejs ?
Eg.:
@component.register("calendar")
class Calendar(component.Component):
# This component takes one parameter, a date string to show in the template
def get_context_data(self, date):
return {
"date": date,
}
template = """
<div class="calendar-component">Today's date is <span>{{ date }}</span></div>
"""
css = """
.calendar-component { width: 200px; background: pink; }
.calendar-component span { font-weight: bold; }
"""
js = """
(function(){
if (document.querySelector(".calendar-component")) {
document.querySelector(".calendar-component").onclick = function(){ alert("Clicked calendar!"); };
}
})()
"""
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
EmilStenstrom commentedon Oct 17, 2022
This is a great idea. I have thought of ways of making this happen. I don't think I like having everything as strings, because you lose all syntax highlighting in editors. Is there a way to get syntax highlighting some other way?
vb8448 commentedon Oct 17, 2022
Pycharm seems to support language injections and I guess also vscode does. Probably a specific extension will be needed.
EmilStenstrom commentedon Oct 18, 2022
I did some reading on this, and found a couple of crazy solutions such as https://github.com/twidi/mixt/ which have solved this in a mix of crazy and fantastic. But there's really nothing good out there. Language injections works in pycharm, but not in vscode. This also bypasses Django's template loading system, which loses caching.
Overall, I think using strings like in your quick example would quickly break down for bigger components. So right now it's a "wontfix".
I do really like to have a solution for this, but I just don't see a solution I'd like to recommend to users. Losing syntax highlighting in editors seems like the major one right now.
aymericderbois commentedon Nov 2, 2022
I love the idea of having the template directly in a component variable. This is especially useful when you want to make small components!
Unfortunately for syntax highlighting, I think there is no solution. Even with Pycharm, the support of language injections is limited.
Nevertheless, as this is the kind of functionality I could use, I tried to make some tests and I made a quick development that allows to have "inline template".
Here is a "countdown" component, with the template directly in the component :
The commit applying the modification is here : aymericderbois@d650a92
The advantage of this implementation is to keep the use of the Django template system. I did this quickly, so I guess it could be greatly improved.
EmilStenstrom commentedon Nov 4, 2022
Thanks for taking the time to show how it could look like.
I really don't like the developer ergonomics of having to write html, css, and js inside of python strings. If there was (when there is?) a way to enable syntax highlighting in some clever way, I would be OK with this change. But as it stands, I don't think we should encourage that kind of code, and instead only support having separate files in a directory.
Since all the changes are in the Component class, I think you could make your own component base, and inherit from that inside your project? That way, we wouldn't have to build this as part of the core django-components.
EmilStenstrom commentedon Dec 17, 2022
Hmm. I keep thinking about how to get this done, because it would a lot simpler. Maybe we should write a custom VSCode extension that can highlight our custom file format?
EmilStenstrom commentedon Dec 19, 2022
I have opened the following PR to try to get editors to highlight this code: microsoft/vscode#169560
EmilStenstrom commentedon Feb 3, 2023
The Python extension people with VSCode are currently thinking about adding support for this (!). All we need right now are more upvotes on this ticket: https://www.github.com/microsoft/pylance-release/issues/3874
Is this something that you, or your colleague, or maybe your grandmother would find useful? Please add a 👍 to that issue, and tell your friends! We're doing this!!
rtr1 commentedon May 15, 2023
I was able to get syntax highlighting to work using https://github.com/samwillis/python-inline-source
EmilStenstrom commentedon May 16, 2023
@rtr1 This is FANTASTIC news! This solved the major pain point I see with having inline components like this. I'm definitely open to allowing inline css/javascript now! Maybe also template code?
rtr1 commentedon May 17, 2023
I got two Tailwind VS Code extensions to work inside Python strings.
Now with
Tailwind
, Alpine, and HTMX, I'm making Django components with only the.py
file. I love it!In VS Code's
settings.json
:And then using Tailwind CLI, in
tailwind.config.js
:EmilStenstrom commentedon May 17, 2023
@rtr1 Sounds great! Do you run a fork of django-components that supports inline strings? Would you mind submitting a PR?
7 remaining items
nerdoc commentedon Jul 24, 2023
I dislike the idea of single file components, not because it is not convenient, but it has major drawbacks for devs. Even when syntax highlighting works, you loose things like auto suggestions, click-to-navigate to code, IDE's understanding of the code structure etc.
There is another framework: Tetra, that solves this using the VSCode plugin. PyCharm does not works at all yet besides Syntax highlighting (manually). So -1 for this, efforts are better spent into other features IMHO...
rtr1 commentedon Jul 24, 2023
I see at least two distinct scenarios.
One is what @nerdoc brings up. I think if one has extensive JS or CSS in a component, this a very valid point, and becomes more valid as the complexity of those pieces of the puzzle increase.
Two is using a “low/no JS” approach, like utilizing Tailwind and Alpine. This scenario can basically already be done with existing tooling, IDE extensions, etc.
So it may be the case that, the only practical application of SFC is one which is already possible, and no further changes would be needed. At least, it’s worth considering if this is the case or not.
EmilStenstrom commentedon Jul 24, 2023
@nerdoc To be clear: The suggestion here is not to replace all existing multi-file components with single-file components. but to add single-file components as an option. If you have a complex component, that would likely be in multiple files, but simple ones could be in a single file. Again, this would be optional for you as a user, and I wouldn't want to break backwards compatibility by removing multi-file components.
nerdoc commentedon Jul 25, 2023
Yeah, thats what I thought. As long as the "traditional" approach stays, a single file approach would reallly be a perfect addition.
dylanjcastillo commentedon Dec 17, 2023
Would it be too crazy to have something in between? Not exactly a SFC, more like a single-file UI component + python component:
Something like this:
UI component:
Python Component:
The UI component would be an HTML file, so you get syntax highlighting, etc for free but you also get more LOB on the UI side of things.
EmilStenstrom commentedon Dec 17, 2023
@dylanjcastillo With HTMX and Tailwind, you are not as likely to need any style and js files at all. So I guess you can do that already...
I think the value here is having the python file contain everything you need. If it's two or four files matters less. The VSCode extension above solves inlines color highlighting nicesly.
So to me, this is just a matter of who will write the PR?
dylanjcastillo commentedon Dec 19, 2023
Hey @EmilStenstrom, I agree that the single Python file is ideal, but you'd lose things like auto-formatting of the file (e.g., Prettier, djlint), which would reduce this to only very simple components.
OTOH, I'd like to get a bit more understanding of the codebase, and this could be a good starting point. So after I finish a project by the end of the month, I'll take a shot at this.
ekaj2 commentedon Jan 5, 2024
EmilStenstrom commentedon Jan 6, 2024
@ekaj2 Thanks for the neovim link, lots of good inspiration!
As I've said before, my view is that it's already possible to embed script and css in the template file if you want. Just inline the CSS with tailwind and put the js in a script tag. The python file is then likely small enough to be easy to do. I've created an issue to maybe make this workflow even easier #337, but I'd say it's a nice to have.
@ALL Single file components in the python file is probably best for small components, with just a few lines of template code, or CSS, which in my experience most components are. This means that automatic formatting within those strings is not as useful, although if someone finds a way to support that it would of course be nice.
So let's focus on putting everything in the python file for in this issue.
Design suggestion
There are four languages that we want to support in this single file: Python, HTML, CSS, and JS.
Python: Since we already are within a python file, that case is solved :) ✅
HTML: Importing Template from django.template as in #183 (comment) solves this nicely I think. No need for a separate template file.
CSS and JS: This is what I'd like to fix, supporting putting your code in strings instead of as links to separate files.
Syntax idea:
And maybe there should be an even simpler API where you just put your code in a variable with a special name:
EmilStenstrom commentedon Jan 14, 2024
Fixed by #361, thanks @dylanjcastillo!
EmilStenstrom commentedon Jan 14, 2024
This is now released as version 0.32 on PyPI: https://pypi.org/project/django-components/0.32/