44 ms·
As a somewhat active Dash user, I wonder why is it that most of these frameworks have chosen to go this "write-HTML-in-Python" way, instead of what seems to me
by low_tech_love 4y ago
As a somewhat active Dash user, I wonder why is it that most of these frameworks have chosen to go this "write-HTML-in-Python" way, instead of what seems to me a much more natural approach: write some basic, stripped down HTML/CSS in a separate file, then connect that automatically to your backend by e.g. using the right IDs.
Let me give an example. In the Increment/Decrement we see the following Python code:
def index():
return pc.hstack(
pc.button(
"Decrement",
color_scheme="red",
border_radius="1em",
on_click=State.decrement,
),
pc.heading(State.count, font_size="2em"),
pc.button(
"Increment",
color_scheme="green",
border_radius="1em",
on_click=State.increment,
),
)
Which is supposed to build the interface for this almost-too-simple example. Note how there is a lot of custom Python code for simple HTML and CSS things that are already directly available in, well, HTML and CSS. This is how it might look like instead (pardon the inline CSS, it's just a quick comment, you can of course make this much better by writing the CSS separately):
<button id="dec_btn" class="red" style="border-radius: 1em;">Decrement</button>
<h2 id="count_h" style="display: inline; font-size: 2em">0</h2>
<button id="inc_btn" class="green" style="border-radius: 1em;">Increment</button>
Then in the Python side, something like:
pc.event(id='dec_btn', type='on_click', action=State.decrement)
pc.event(id='inc_btn', type='on_click', action=State.increment)
# Runs everytime the State changes (or something)
def global_update():
pc.print(id="count_h", f'{State.count}')
This way, presentation is separated from business logic, and 'everything in its right place' (c).
I understand that many (most?) Python developers would like to stay away from JS, but I expect that most developers will know 80% of what is needed from basic HTML/CSS in order to do something like this. If they don't, it should be really easy to learn. I mean, come on, basic HTML/CSS is like a foundational building block of computing, and anyway, to write "HTML-in-Python" you still need to learn the basics (and then twist them into their Python doppelganger).
- serial_dev 4y agoI think it's a more natural approach to you (and many others, including me a couple of years ago) because that's the way we used to do things, both on web (JavaScript, CSS, HTML) and Android (Java, XML), and who knows where else. If you stop for a second and think about whether or not it's actually natural, you'll quickly realize that it's not, it's just something you are used to. I cannot give you anything Python specific, but I can share my experience with Flutter and Dart. In Flutter, you build your UI using regular Dart code and it feels great. This approach, btw, is also similar to Compose and SwiftUI (and to a lesser degree, JSX). Here are the pros: You don't need to switch from Java to XML, or from JavaScript to CSS/HTML, you can do everything using the same language. Instead of learning 2 or 3 languages (and their respective tools for testing, analyzing, linting, coding conventions), you can learn one well. You need to do some semi-advanced logic on the button label or classes? No problem, just write the language you write everywhere. An IIFE solves your problem nicely? It's okay, you can just use it. If you like working with Rx streams, or any other library, you can keep using them in your UI, no glue-libraries are needed. Need to debug or add logging, printing, error reporting? Your toolchain already supports that. Your IDE has terrible support for "insert templating language"? Not gonna happen here, if your IDE supports Dart (or in Pynecone's case, Python), you are good to go: you can jump to definitions, you can refactor argument names, and you can lookup usages exactly the way you are used to. You don't need to learn special syntax for conditionals, for loops, and whatnot, you just use your primary language. In Dart's case, you also win with the typing: if a widget expect a callback that receives a User instance and returns an integer, you can define that and making sure that instead of runtime errors, you will see the errors in your IDE as you type. You also don't need to worry about different naming conventions. If you app calls it userIds, your UI will also call it userIds, instead of "user-ids", or "user_ids".
- mainframed 4y agoI'm also using Dash to create a quite complex multi-page app. And I agree with you, at the beginning, it somewhat annoyed me, that this can lead to very verbose nested statements, but since I started refactoring most code into reusable components (AiO), I don't think anymore, that separated html-files would lead to a better usability. I would have a lot of small html-files. Also, I want to dynamically set the ids, so I can connect some components. Hence, I would need to use some templating engine for inserting the ids. This works well with django, which I used for a long time, but I don't think it works with React-based apps, which are very component-driven.