Элемент, добавленный в DOM, имеет атрибуты HTML / SVG, но не имеет соответствующих свойств JS

Я использую HTMX с Django для рендеринга страницы, которая в основном представляет собой SVG с большим количеством липких заметок (), которые вы можете перемещать по странице, как вы могли бы использовать для мозгового штурма. Когда вы редактируете текст, htmx отправляет его обратно в представление Django, которое возвращает обновленное содержимое.

Это шаблон Django для одной формы:

<g id="g1-{{form.instance.pk}}"
   hx-post="{% url 'architech:updatetech' form.instance.map.pk form.instance.pk %}"
   hx-swap="outerHTML"
   hx-trigger="focusout"
   hx-include="#fo-{{form.instance.pk}}">
<g id="g2-{{form.instance.pk}}" transform="{{form.instance.presentation|safe|default:"matrix(1,0,0,1,50,50)"}}" class="ui drags" draggable="true">
<foreignObject id="fo-{{form.instance.pk}}" height="203" width="319">
<form class="card"
      id="form-{{form.instance.pk}}"
      draggable="true">
<div id="header-{{form.instance.pk}}" class="card-header" draggable="true">
    {{ form.name.errors}}
    {{ form.name }}
    {{ form.presentation }}
    <input type="button" value="x" hx-post="{% url 'architech:deletetech' form.instance.map.pk form.instance.pk %}"
           hx-swap="outerHTML" hx-target="#g-{{form.instance.pk}}" hx-trigger="click">

</div>
<div id="body-{{form.instance.pk}}" class="card-body" draggable="true">
    {{ form.notes.errors}}
    {{ form.notes }}
</div>
</form>
</foreignObject>
</g>
</g>

Я использовал hx-swap="outerHTML" (и недавно "morphdom") для повторного рендеринга и замены этого блока кода. При повторной загрузке тот же SVG/HTML не отображается правильно и не реагирует на javascript.

Ключевым элементом является вторая группа, id которой начинается с g2.

При загрузке всей страницы высота и ширина соблюдаются, а атрибуты типа 'transform' доступны с помощью element.transform:

# console interaction on initial state using 'save to a global variable'
>temp1
  <g id="g2-22a443de-35c4-4bcd-8b48-183961c9d363" transform="matrix(1, 0, 0, 1, 1870, 1080)" 
  class="ui drags" draggable="true">
>temp1.transform
  SVGAnimatedTransformList {baseVal: SVGTransformList, animVal: SVGTransformList}

Когда тот же SVG/HTML загружается через htmx с hx-swap="outerHTML" или "morphdom", я могу видеть в инспекторе, но он отображается в размере 0 x 0, и element.transform равен null.

# console interaction on reloaded state
>temp1
  <g id="g2-22a443de-35c4-4bcd-8b48-183961c9d363" transform="matrix(1, 0, 0, 1, 1870, 1080)" 
  class="ui drags" draggable="true">"10" id="id_notes">[[Children]]</g>
>temp1.transform
  undefined

Для исследования я в основном использую Chrome и Firefox на Win 11, если это имеет значение.

Буду рад некоторым подсказкам - очень вероятно, что я неправильно понимаю что-то основное о последовательности событий в рендеринге в браузере или о том, как сделать Namespace явным или что-то еще. (Я думал, что у меня была эта проблема [setAttribute не работает] в течение некоторого времени и все еще немного не уверен в механике, которая вызывает это. )1setAttribute не работает в JavaScript

По ссылке в моем комментарии был найден путь к решению этой проблемы, но хотя он работает, он не очень красивый, и может быть куча причин, чтобы не делать этого. В любом случае, версия jQuery была:

$("#content").html($("#content").html());

Я покопался в исходниках jQuery с помощью jQuery Source Viewer и обнаружил, что часть, которая делает всю работу, в основном получает измененный innerHTML региона и устанавливает innerHTML, который запускает ??????? (рендеринг, регистрация в DOM, что еще???), решая мои проблемы. Я добавил следующую строку в слушатель события htmx:afterSettle. Она обновляет весь внутренний HTML, так что все элементы теряют любые слушатели событий или специальные свойства, которые вы для них создали. Это работает для моего примера: возьмите div, содержащий документ SVG, который содержит элементы svg foreignObject, содержащие HTML.

document.getElementById("mapdiv-{{map.pk}}").innerHTML = document.getElementById("mapdiv-{{map.pk}}").innerHTML;
Вернуться на верх