Fix issues using ListEditWidget with more complex sub-widgets.

Review Request #13412 — Created Nov. 13, 2023 and submitted

Information

Djblets
release-3.x

Reviewers

A couple issues were encountered when trying to embed some complex
widgets (containing a MultiWidget with inline <script> tags) inside
of a ListEditWidget.

First, the default row template was not escaped when rendering it in the
template as an option for the view. This is not a security issue, as
this is app-provided HTML, and does not make use of user-provided input
(unless the application is doing something very custom). This has been
updated to properly escape.

Second, IDs weren't being passed in to sub-widgets, which could affect
their ability to render and set up their state. This was made more
complex when sub-widgets had inline scripts or other complexity needed
for setup, particularly because we need to be able to pass in some sort
of default template for a row, and have that customized in the
JavaScript side.

To resolve that, we now hard-code some placeholder constants within the
template, representing the ID and name, and then fill those in when
creating a new instance in JavaScript. We provide a unique ID that won't
change (to avoid disassociating state when reordering rows), and a name
that may change (due to reordering on delete).

Some other optimizations were made to avoid repeated DOM lookups for the
same element.

This overall makes it easier to work with more complex sub-widgets
within this widget. There are things it still can't do, like
cooperatively work with a field that wants to clean up on delete, but
that's not an immediate concern.

Python and JavaScript unit tests pass.

Tested existing and in-progress usage of the field and widget.

Summary ID
Fix issues using ListEditWidget with more complex sub-widgets.
A cuple issues were encountered when trying to embed some complex widgets (containing a `MultiWidget` with inline `<script>` tags) inside of a `ListEditWidget`: First, the default row template was not escaped when rendering it in the template as an option for the view. This is not a security issue, as this is app-provided HTML, and does not make use of user-provided input (unless the application is doing something very custom). This has been updated to properly escape. Second, IDs weren't being passed in to sub-widgets, which could affect their ability to render and set up their state. This was made more complex when sub-widgets had inline scripts or other complexity needed for setup, particularly because we need to be able to pass in some sort of default template for a row, and have that customized in the JavaScript side. To resolve that, we now hard-code some placeholder constants within the template, representing the ID and name, and then fill those in when creating a new instance in JavaScript. We provide a unique ID that won't change (to avoid disassociating state when reordering rows), and a name that may change (due to reordering on delete). Some other optimizations were made to avoid repeated DOM lookups for the same element. This overall makes it easier to work with more complex sub-widgets within this widget. There are things it still can't do, like cooperatively work with a field that wants to clean up on delete, but that's not an immediate concern.
2a4d22063f6a3c91e1375d724eee6f32068991b4
Description From Last Updated

Typo in description: cuple -> couple

daviddavid
maubin
  1. Ship It!
  2. 
      
david
  1. 
      
  2. Show all issues

    Typo in description: cuple -> couple

  3. 
      
chipx86
chipx86
Review request changed
Status:
Completed
Change Summary:
Pushed to release-3.x (db8795e)