Closed KoenLav closed 8 years ago
Ah, I see I can fix this using jQuery .change() after updating the value...
The really big advantage of using the viewmodel pattern, is that you never have to update the DOM manually – all you do is update the viewmodel, and the bindings take care of the rest.
You can say, that if you ever use jQuery outside of a custom binding definition, then you are doing it wrong ;)
Instead of updating the textarea with val()
, just set the new value on the textarea's viewmodel. This viewmodel can be retrieved, preferably, by selecting it with one of the traversal methods (this.child()
), or, alternatively, with one of the static methods ( ViewModel.findOne()
), in case it is in a totally different part of the view hierarchy.
Let me pick your brain here a little:
We have a jQuery on-screen keyboard which changes the value of the currently focussed element, so there is (as far as I know) no easy way of determining which viewmodel we are updating.
Would you then still say that this is 'wrong'?
As long as you have the actual DOM element of the textarea, then you can get to Blaze world using Blaze.getView(element)
.
From there, you can traverse the view hierarchy until you get the template instance, which has a viewmodel
property. If you simply need to update the property bound to the element in question, do this (ES6 syntax):
const dom_elem = $(".my-textarea")[0];
const blaze_view = Blaze.getView(dom_elem);
const binding_nexus = blaze_view.nexuses.findOne(nexus => nexus.elem === dom_elem && nexus.name() === "value");
const viewmodel_prop = binding_nexus.getProp();
// Set new value
viewmodel_prop("New text in textarea");
// Get value
viewmodel_prop(); // "New text in textarea"
EDIT: The above can be achieved in 1.0.0
with:
const dom_elem = document.querySelector(".my-textarea");
// Set new value
ViewModel.Nexus.findOne(dom_elem, "value").prop("New text in textarea");
Hi Kristian,
I expected this was possible, but do you think that this is the 'correct' solution in this particular situation? It seems like this approach is more likely to break under different circumstances than using .val().change() in the keyboard.
I have to agree that it's probably a cleaner solution to keep your jQuery plugin in jQuery land. Library ignorance is bliss ;)
Hehe, was just wondering whether you might have some insight which could convince me otherwise :)
Thanks!
Np, don't hesitate to ask again.
P.S. I would consider adding a couple of static convenience methods to ViewModel
:
ViewModel.getViewmodel(dom_element)
ViewModel.getProp(dom_element, binding_name)
I've made some API changes along the lines of my previous comment. You can check out the part most relevant to your original question in the third code example in the Static methods section. I've also updated my previous answer in this thread.
After a long time with no issues, I've also become ready to release version 1.0.0
of the package.
The new version should be compatible with the previous version 0.9.4
, except that I've removed jQuery as a dependency, which means that elements and events are no longer wrapped by jQuery.
See the History section.
Nice! :+1:
When I have a textarea and bind it using {{bind "value: text"}} and then use jQuery (in another viewmodel) to modify the .val() of the element that is bound this does not trigger an update of the viewmodel property (text) even though the value of the element has changed.