up-follow and up.compiler in script tags

158 views
Skip to first unread message

thinkwel...@gmail.com

unread,
Jun 11, 2021, 2:59:52 PM6/11/21
to unpoly
Hello Henning,

I'm about finished migrating to Unpoly v2 and the last thing I thought I'd try to get figured out is getting Datatables to work with up-follow - found my original question here.

In doing more research, I came across Why was script tag execution removed on 0.51, and I got the bright idea of hoisting my DataTables code out of the in-page script tag and put it into an external javascript file.

Sure enough, then it worked; somehow I never quite thought of trying external files before, and the ramifications of using script tags when using up-follow.

However, that still has me scratching my head.  Why does Unpoly provide up-follow at all, much less make it easier to use in v2, if all JS must be linked to external files. 

I dowanna define my DataTables JS in external files, as the JS is rendered from Django templates. It's not the end of the world; I don't have to use up-follow at all. The only remaining issue is redirects after deletions has to be handled outside of Unpoly.

In conclusion, if this is the way it has to be, then fine. If so, FWIW, it would've saved my hours of time if the documentation pointed out that up-follow can't fire embedded script tags. 

Additionally, it'd be worth a similar note at the up.compiler page, to warn that pages reached by up-follow won't work.

But such severe strictures have me still wondering if I'm doing something wrong. Why make up-follow at all if it borks all embedded javascript? 

If I'm doing something wrong, would be glad to know...

P.S. Here's an example datatables invocation that doesn't work when visited with up-follow, but does work if referenced in external script. (of course all the Django template variables have to be replaced in the external script...)



thinkwel...@gmail.com

unread,
Jun 11, 2021, 6:10:07 PM6/11/21
to unpoly
It occurred to me that there has to be a way to pass state to javascript files, and of course there is...

<script id="datatables"
src="{{ STATIC }}/deployed/user_list.js"
data-filters="{{ view.table_filters }}"
data-current_app="{{ CURRENT_APP }}"
data-model_name="{{ view.model_name }}"
data-css_icon="{{ view.css_icon }}"
data-icon_company="{{ Icons.COMPANY }}">
</script>


So I'm getting my in-page scripts converted to src files...that's getting me past the problem. I still think it'd be useful to have more clear docs on this issue, but overall your docs are great! Thanks again for Unpoly.

randl...@googlemail.com

unread,
Jun 12, 2021, 9:57:12 AM6/12/21
to unpoly
Why make up-follow at all if it borks all embedded javascript? 

There are many upsides to avoiding full page loads that have nothing to do with script tags. These include to not force the browser to reload all CSS and JS on every click, to preserve transient state like focus and scroll positions, or to enable animated transitions.


Best regards
Henning 

thinkwel...@gmail.com

unread,
Jun 15, 2021, 4:42:02 AM6/15/21
to unpoly
Thanks for the reply, Henning, and thanks for the link to the run inline script tags page.

My question is now resolved, but I'm not quite sure that my remaining observation about docs/terminology is being understood, which in short is that there's a 2-step process that is only being referred to as if it's a one-step process.

In your answer above, you said "While it's still recommended to call all your JavaScript from compilers" but as my code examples made quite clear, I already was calling JS from up.compiler. My problem was that I hadn't migrated script tags to an external file, which is an all-important unpoly requirement. It'd be nice to have clearer docs on this point, right on the up.compiler page. Would you be open to a PR?

Also, help search could've worked better. I'd repeatedly tried to search for "script" and "script tags", etc and came up with nothing, so i posted this question. Now that I now where to read about inline script tags, I tried to search and find it, but I still can't find the page by searching. (Tried "legacy" and "runScripts", for example)

So again, my question is resolved; thanks a million. I hope to release a django implementation of the Unpoly Server Protocol sometime soon.

randl...@googlemail.com

unread,
Jun 15, 2021, 11:23:31 AM6/15/21
to unpoly
In your answer above, you said "While it's still recommended to call all your JavaScript from compilers" but as my code examples made quite clear, I already was calling JS from up.compiler. My problem was that I hadn't migrated script tags to an external file, which is an all-important unpoly requirement. It'd be nice to have clearer docs on this point, right on the up.compiler page. Would you be open to a PR?

Doc improvements are always welcome. However, I'm not sure that you're using compilers the way they were intended.

Having no experience with the DataTable plugin or your particular app, I assume that your code looked like the snippet below pre-Unpoly, when you were making full page loads. After every record list there was an inline-script tags initializing the DataTable plugin with options specific to the record type ("users", "documents"). A shortened example:

<!-- users.html -->
<div class="users_list">
  ...
</div>

<script>
$('.users_list').DataTable({
  ...,
  ajax: { url:  "/api/lc/users" },
})
</script>


<!-- documents.html -->
<div class="documents_list">
  ...
</div>

<script>
$('.documents_list').DataTable({
  ...,
  ajax: { url:  "/api/lc/documents" },
})
</script>

When you migrated to Unpoly you expected the following to work:

<!-- users.html -->
<div class="users_list">
  ...
</div>

<script>
up.$compiler('.users_list'), function($element) {
  $element.DataTable({
    ...,
    ajax: { url:  "/api/lc/users" },
  })
)
</script>


<!-- documents.html -->
<div class="documents_list">
  ...
</div>

<script>
up.$compiler('.documents_list'), function($element) {
  $element.DataTable({
    ...,
    ajax: { url:  "/api/lc/documents" },
  })
)
</script>

However, compilers are not meant to "run JavaScript now". They are meant to run JavaScript whenever an element matching .users_list or .documents_list enters the DOM in the future.

If the code above would work, we would register the same compilers again and again as users navigate back and forth using [up-follow] links. Eventually we would initialize the DataTable plugin many times for each .users_list and .documents_list element that enters the DOM via a fragment updates.

Preventing duplicate compiler registrations were one of the motivations to not evaluate script tags in new fragments.


The canonical way to implement this would be to have no <script> tags at all to activate a data table, neither inline nor external. Instead we would only render the record list with type specific parameters in an [up-data] attribute:

<!-- users.html -->
<div class='list' up-data='{ "model_name": "users" }'>
  ...
</div>  

<!-- documents.html -->
<div class='list' up-data='{ "model_name": "documents" }'>
  ...
</div>

We then have a single compiler, loaded once in the document <head> that initializes the DataTable plugin. The type-specific options from the [up-data] attribute are automatically passed as a second compiler argument:

<!-- scripts.js -->
up.$compiler('.list', function($element, data) {
  $element.DataTable({
    ...,
    ajax: { url:  "/api/lc/" + data.model_name },
  })  
})
 
Also, help search could've worked better. I'd repeatedly tried to search for "script" and "script tags", etc and came up with nothing, so i posted this question. Now that I now where to read about inline script tags, I tried to search and find it, but I still can't find the page by searching. (Tried "legacy" and "runScripts", for example)

I agree. The current search only looks through document titles. It would be much better to integrate something like Algolia.
 
I hope to release a django implementation of the Unpoly Server Protocol sometime soon.

That's great!

Let me know if you choose to release it, then I can feature it as a Python option on https://unpoly.com/install .

Best regards
Henning

Gustavo Gawryszewski

unread,
Jun 17, 2021, 3:58:39 PM6/17/21
to unp...@googlegroups.com
Curiously I had the same issue when I first started, but then I realized moving to a separate would be better.

After that, I've added a JS router so I could have more control over the JS that runs for each page.

Gustavo Gawryszewski
Mobile: +55 21 99119-2790
Website: http://gawry.com
LinkedIn: http://www.linkedin.com/in/gawry


--
You received this message because you are subscribed to the Google Groups "unpoly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to unpoly+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/unpoly/fb931147-32ef-46b9-bb8d-ba5de7115c01n%40googlegroups.com.
Message has been deleted

Jannik Waschkau

unread,
Jun 30, 2021, 10:06:26 AM6/30/21
to unpoly
thinkwel...@gmail.com schrieb am Dienstag, 15. Juni 2021 um 10:42:02 UTC+2:

So again, my question is resolved; thanks a million. I hope to release a django implementation of the Unpoly Server Protocol sometime soon.


 Hey,

maybe we can work together building a Django implementation for Unpoly. I already started development a few weeks ago and use it in our products. The project is published on GitHub (https://github.com/jwaschkau/django-unpoly) and PyPi (https://pypi.org/project/django-unpoly/).

Let me know what you think or what features are missing .

Best regards,
Jannik

thinkwel...@gmail.com

unread,
Jul 2, 2021, 4:34:53 PM7/2/21
to unpoly
Hello Jannik,

I didn't realize you were building an unpoly django implementation until I went to publish my module to pypi and discovered that another project with the same name had been registered a few days before.

Here's my repo - https://github.com/thinkwelltwd/unpoly_django. It was refactored out of a django app that I'm responsible for, as I wanted to re-use the code in several other consoles and I decided to make it generally available.

Yours is simpler and more docs; so it'd work better. Mine probably goes a bit beyond the actual server protocol with some settings, mixins and hooks to enable support for Crispy Forms and optimized responses.

Anyway, now there's great django support for Unpoly, and if Henning wants to include both on the Server Protocol page, that's fine with me.
Reply all
Reply to author
Forward
0 new messages