Hi! Is it possible to manipulate input values using LiveView.JS?
In the following example (sample app on GitHub), I can successfully change the value of #my-input to Hello or World depending on which button I click first. Subsequent button clicks do not do anything.
How come after the first button click nothing happens?
Is it possible to append to an existing input value so that clicking buttons âAdd âHelloââ and âAppend âWorldââ in sequence would change the value to âhelloworldâ? (My example doesnât show this, but I didnât find anything to access the inputâs current value in the docs).
I suspect that JS.set_attribute isnât the right way to interact with client-side forms this way.
Maybe JS.dispatch is? How else would you go about this?
I want to interact with a form element before having to send information to the server. I can use Alpinejs, but Iâm trying to avoid a dependency unless itâs absolutely essential.
function append(value) {
let el = document.getElementById("#my-input")
el.value = el.value + value
}
function reset() {
let el = document.getElementById("#my-input")
el.value = ''
}
set_attribute is for html attributes. Its js equivalent is el.setAttribute("value", âŠ). The value attribute on inputs sets the default value for that input.
el.value = ⊠however sets a property on the dom object behind the html and edits the actual value, not the default.
I hope that explains why you get the behaviour you see.
I think the LiveView-way of doing this would be to use phx-click and friends, and make a network round-trip. You will have to use the form helpers or bind the input field yourself somehow. You will probably have to make the roundtrip anyway to do live validation. This way you wonât have to add any dependencies, and stay on the LiveView golden path.
Hi. In this case, itâs wasteful and adds unnecessary latency to go to the server and back. The server does nothing but update a GenServer and waits on standby to act later. It would be better to mount the state on the client-side first and send it once it can be acted upon by the GenServer. There is no validation during this phase.
I have it working via round-trip. But I find it adds latency, complexity to the GenServer, and no meaningful value (other than working). I need quicker feedback on the client before going to the server.
I think the LiveView way to do this is indeed via JS.dispatch. The live_beats app is a good reference for these kind of things. For example they have a js_exec method via which you can call arbitrary functions on the target element.
However in your case, since you need to assign a property, it would look something like this though:
window.addEventListener("js:set", e => e.target[e.detail.key] = e.detail.value);
Then use JS.dispatch like this:
JS.dispatch('js:set', to: "#my-input", detail: %{key: "value", value: "hello"})
Or even simpler:
window.addEventListener("js:set_input_value", e => e.target.value = e.detail);
JS.dispatch('js:set_input_value', to: "#my-input", detail: "hello")