Knockout.js gets the dom object associated with the data

I am working with knockout.js to create dynamic lists, and I am trying to figure out how I can get the DOM object associated with the object in my observable array. In particular, I want to get jQuery for a string.

Example:

<ul data-bind="foreach: Item"> <li data-bind="events: {click: getDomObject}, text: 'text: ' + text"> </li> </ul> 

in the getDomObject function, I would like to be able to get a specific <li></li> DOM object so that I can manipulate jQuery with it.

I thought about adding an id member to the ViewModel element, and then add an identifier as the identifier of the html position and then select it based on this, but I think there should be an easier way.

What is the correct way to link to dynamic HTML created by knockout.js?

+46
jquery dom
Apr 12 2018-12-12T00:
source share
5 answers

Event handlers such as click pass two arguments. This is a) the element to which this event belongs - as a record of an observable array that you visualize with a foreach binding ("Item" in your case). And b) an event object that provides you with more information about the actual event. This object contains the DOM element that was pressed (key "target"):

 getDomObject = function(item, event) { var $this = $(event.target); // ... } 

Just note: don't mix knockouts and your own manipulations with DQ JQuery - if you can achieve the same result with smart knockout bindings, I would recommend that with that.

And here is a simple demo: http://jsfiddle.net/KLK9Z/213/

+64
Apr 12 2018-12-12T00:
source share

The solution $ (event.target) is good if it is associated with an event already occurring in which the element's DOM element is in the object. But sometimes you don’t have a target element, because there is no event (for example, you want to scroll to an element that was not specified by the user).

In this case, you can assign the id attribute of the DOM element element a unique value that contains the element identifier:

 <li data-bind="attr: {id: 'item_' + id}"> 

and then getDomObject () looks like this:

 getDomObject = function(item) { return $("#item_" + item.id); } 
+20
Aug 22 2018-12-12T00:
source share

To add another third option, also for cases when you do not have an event to work with (if you have an event, the accepted answer is better / optimized).

Create a custom binding, for example:

 ko.bindingHandlers.scrollTo = { update: function(element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()); if (value) { var scrollParent = $(element).closest("div"); var newTop = $(element).position().top + scrollParent.scrollTop(); scrollParent.scrollTop(newTop); } } }; 

The following is used:

 <li data-bind="scrollTo: $parent.scrollTo() && $parent.scrollTo().id == id"> 

In the above case, $ parent is my view model. I have an observable object that contains a unique identifier. Each time I set this scrollTo () object, the list scrolls to this element.

Please note that my code assumes that the parent DIV LI has a scrollbar (overflow: auto / scroll). You can customize for your needs, perhaps use a class for the parent and use it for your jQuery selector or make it very flexible so that you can go to the selector via data binding options ... this was enough for me since I always use divs for of my scrollable sections.

+7
Feb 18 '13 at 3:49
source share

I had a similar problem. I come up with a solution reminiscent of Backbone.js using el and $ el links.

in your ViewModel:

 var myViewModel = function(){ var self = this; //html element self.el = ko.observable(); //jquery wrapped version self.$el = ko.observable(); } 

in html (e.g. list item):

 <!-- left side is the name of the handler, right side is name of the observable --> <li class="myclass" data-bind="el: el, $el: $el"></li> 

in bindHandlers (showing all possible arguments for init):

 ko.bindingHandlers.el = { init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { var value = valueAccessor(); //assign value to observable (we specified in html) value(element); } }; ko.bindingHandlers.$el = { init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { var value = valueAccessor(); //here we first create a jQuery object by using $(myelem) //before updating observable value value($(element).first()); } }; 

For example, you can use $ el, for example:

 var myViewModel = function(){ var self = this; //plain DOM element reference self.el = ko.observable(); //jquery object reference self.$el = ko.observable(); self.myFunction = function() { console.log(self.$el().html()); self.$el().addClass("myCssClass"); } } 

Hope this helps!

+1
Dec 29 '15 at 9:45
source share

My solution (valid for value binding)

  ko.bindingHandlers.value.preprocess = function(val, name, cb) { /* every time I set a data-bind="value: xxxx" with an * observable xxxx add also a data-bind="domElement: xxxx" */ cb('domElement', val ); return val; } ko.bindingHandlers.domElement = { /* For each data-bind="domElement: xxxx" add an extension "element" */ init: function (element, valueAccessor, allBindingsAccessor, viewModel) { valueAccessor().extend({element: element }); } }; ko.extenders.element = function (target, element) { /* element extension add el and $el to observable xxxx */ target.el = element; target.$el = $(element); } 

Now you have yourobservable. $ el and yourobservable.el that bind to the jquery and DOM element.

+1
Nov 17 '17 at 10:50
source share



All Articles