Skip to content

Commit 04a987b

Browse files
Fix JS.exec with scope selector (#3678)
* add tests * fix exec_exec function to use already filtered element
1 parent 4553156 commit 04a987b

File tree

2 files changed

+63
-6
lines changed

2 files changed

+63
-6
lines changed

assets/js/phoenix_live_view/js.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,9 @@ let JS = {
4646
// commands
4747

4848
exec_exec(e, eventType, phxEvent, view, sourceEl, el, {attr, to}){
49-
let nodes = to ? DOM.all(document, to) : [sourceEl]
50-
nodes.forEach(node => {
51-
let encodedJS = node.getAttribute(attr)
52-
if(!encodedJS){ throw new Error(`expected ${attr} to contain JS command on "${to}"`) }
53-
view.liveSocket.execJS(node, encodedJS, eventType)
54-
})
49+
let encodedJS = el.getAttribute(attr)
50+
if(!encodedJS){ throw new Error(`expected ${attr} to contain JS command on "${to}"`) }
51+
view.liveSocket.execJS(el, encodedJS, eventType)
5552
},
5653

5754
exec_dispatch(e, eventType, phxEvent, view, sourceEl, el, {event, detail, bubbles}){

assets/test/js_test.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,66 @@ describe("JS", () => {
783783
}
784784
JS.exec(event, "exec", click.getAttribute("phx-click"), view, click)
785785
})
786+
787+
test("with no selector", () => {
788+
let view = setupView(`
789+
<div
790+
id="click"
791+
phx-click='[["exec", {"attr": "data-toggle"}]]''
792+
data-toggle='[["toggle_attr", {"attr": ["open", "true"]}]]'
793+
></div>
794+
`)
795+
let click = document.querySelector("#click")
796+
797+
expect(click.getAttribute("open")).toEqual(null)
798+
JS.exec(event, "click", click.getAttribute("phx-click"), view, click)
799+
expect(click.getAttribute("open")).toEqual("true")
800+
})
801+
802+
test("with to scope inner", () => {
803+
let view = setupView(`
804+
<div id="click" phx-click='[["exec",{"attr": "data-toggle", "to": {"inner": "#modal"}}]]'>
805+
<div id="modal" data-toggle='[["toggle_attr", {"attr": ["open", "true"]}]]'>modal</div>
806+
</div>
807+
`)
808+
let modal = document.querySelector("#modal")
809+
let click = document.querySelector("#click")
810+
811+
expect(modal.getAttribute("open")).toEqual(null)
812+
JS.exec(event, "click", click.getAttribute("phx-click"), view, click)
813+
expect(modal.getAttribute("open")).toEqual("true")
814+
})
815+
816+
test("with to scope closest", () => {
817+
let view = setupView(`
818+
<div id="modal" data-toggle='[["toggle_attr", {"attr": ["open", "true"]}]]'>
819+
<div id="click" phx-click='[["exec",{"attr": "data-toggle", "to": {"closest": "#modal"}}]]'></div>
820+
</div>
821+
`)
822+
let modal = document.querySelector("#modal")
823+
let click = document.querySelector("#click")
824+
825+
expect(modal.getAttribute("open")).toEqual(null)
826+
JS.exec(event, "click", click.getAttribute("phx-click"), view, click)
827+
expect(modal.getAttribute("open")).toEqual("true")
828+
})
829+
830+
test("with multiple selector", () => {
831+
let view = setupView(`
832+
<div id="modal1" data-toggle='[["toggle_attr", {"attr": ["open", "true"]}]]'>modal</div>
833+
<div id="modal2" data-toggle='[["toggle_attr", {"attr": ["open", "true"]}]]' open='true'>modal</div>
834+
<div id="click" phx-click='[["exec", {"attr": "data-toggle", "to": "#modal1, #modal2"}]]'></div>
835+
`)
836+
let modal1 = document.querySelector("#modal1")
837+
let modal2 = document.querySelector("#modal2")
838+
let click = document.querySelector("#click")
839+
840+
expect(modal1.getAttribute("open")).toEqual(null)
841+
expect(modal2.getAttribute("open")).toEqual("true")
842+
JS.exec(event, "click", click.getAttribute("phx-click"), view, click)
843+
expect(modal1.getAttribute("open")).toEqual("true")
844+
expect(modal2.getAttribute("open")).toEqual(null)
845+
})
786846
})
787847

788848
describe("exec_toggle_attr", () => {

0 commit comments

Comments
 (0)