Skip to content

Commit

Permalink
phx-trigger-action: check for cloned tree
Browse files Browse the repository at this point in the history
Fixes #3591.
  • Loading branch information
SteffenDE committed Dec 26, 2024
1 parent 918a765 commit 17e3f04
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 2 deletions.
2 changes: 1 addition & 1 deletion assets/js/phoenix_live_view/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ let DOM = {
isTextualInput(el){ return FOCUSABLE_INPUTS.indexOf(el.type) >= 0 },

isNowTriggerFormExternal(el, phxTriggerExternal){
return el.getAttribute && el.getAttribute(phxTriggerExternal) !== null
return el.getAttribute && el.getAttribute(phxTriggerExternal) !== null && document.body.contains(el)
},

cleanChildNodes(container, phxUpdate){
Expand Down
13 changes: 12 additions & 1 deletion assets/js/phoenix_live_view/dom_patch.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export default class DOMPatch {
let focused = liveSocket.getActiveElement()
let {selectionStart, selectionEnd} = focused && DOM.hasSelectionRange(focused) ? focused : {}
let phxUpdate = liveSocket.binding(PHX_UPDATE)
let externalFormTriggered = null

morphdom(container, clonedTree, {
childrenOnly: false,
Expand All @@ -42,9 +43,19 @@ export default class DOMPatch {
DOM.mergeFocusedInput(fromEl, toEl)
return false
}
if(DOM.isNowTriggerFormExternal(toEl, liveSocket.binding(PHX_TRIGGER_ACTION))){
externalFormTriggered = toEl
}
}
})

if(externalFormTriggered){
liveSocket.unload()
// use prototype's submit in case there's a form control with name or id of "submit"
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit
Object.getPrototypeOf(externalFormTriggered).submit.call(externalFormTriggered)
}

liveSocket.silenceEvents(() => DOM.restoreFocus(focused, selectionStart, selectionEnd))
}

Expand Down Expand Up @@ -228,7 +239,7 @@ export default class DOMPatch {
return false
}
if(fromEl.type === "number" && (fromEl.validity && fromEl.validity.badInput)){ return false }
// If the element has PHX_REF_SRC, it is loading or locked and awaiting an ack.
// If the element has PHX_REF_SRC, it is loading or locked and awaiting an ack.
// If it's locked, we clone the fromEl tree and instruct morphdom to use
// the cloned tree as the source of the morph for this branch from here on out.
// We keep a reference to the cloned tree in the element's private data, and
Expand Down
6 changes: 6 additions & 0 deletions assets/test/dom_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,15 @@ describe("DOM", () => {
test("isNowTriggerFormExternal", () => {
let form
form = tag("form", {"phx-trigger-external": ""}, "")
document.body.appendChild(form)
expect(DOM.isNowTriggerFormExternal(form, "phx-trigger-external")).toBe(true)

form = tag("form", {}, "")
document.body.appendChild(form)
expect(DOM.isNowTriggerFormExternal(form, "phx-trigger-external")).toBe(false)

// not in the DOM -> false
form = tag("form", {"phx-trigger-external": ""}, "")
expect(DOM.isNowTriggerFormExternal(form, "phx-trigger-external")).toBe(false)
})

Expand Down

0 comments on commit 17e3f04

Please sign in to comment.