Estoy trabajando con knockout.js para construir listas dinámicas y estoy tratando de averiguar cómo puedo obtener el objeto DOM asociado con un objeto en mi observables de la matriz. Específicamente quiero conseguir el jQuery de una fila.

Ejemplo:

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

en el getDomObject función, me gustaría ser capaz de obtener el específico <li></li> objeto DOM, así que puedo hacer un poco de jQuery para la manipulación con ella.

He pensado acerca de cómo agregar una id miembro para el Elemento ViewModel y, a continuación, agregar el id de la línea del elemento html id y, a continuación, seleccione la base de que, pero siento que debe haber una manera más fácil.

Cuál es la forma correcta para hacer referencia a la dinámica de código HTML generado por knockout.js?

InformationsquelleAutor joe_coolish | 2012-04-12

5 Comentarios

  1. 66

    Controladores de eventos como, por ejemplo, se pasan dos argumentos. Que es

    1. el elemento que este evento es como la entrada de un observable de la matriz que está renderizado con el foreach de unión («Elemento» en su caso).

    2. Y, un objeto de evento, que proporciona más información sobre el evento real. Este objeto contiene el elemento DOM que consiguió hace clic en (clave de «destino»):

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

    Sólo una nota: no mezclar el golpe de gracia y nativo de jQuery DOM manipulaciones – si se puede lograr el mismo resultado con ingeniosas knockout enlaces, yo recomendaría ir con eso.

    Y aquí es una simple demo: http://jsfiddle.net/KLK9Z/213/

    JS:

    var Item = function(color) {
      this.color = String(color);
      this.setTextColor = function(item, event) {
        $(event.target).css('background', color);
      };
    };
    
    ko.applyBindings(new function() {
      this.Items = ko.observableArray([
        new Item('red'),
        new Item('blue'),
        new Item('green')
      ]);
    }());

    CSS:

    li {
      padding: 2px 10px;
    }

    HTML:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.0.0/knockout-min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <ul data-bind="foreach: Items">
      <li>
        <button data-bind="click: setTextColor, text: 'Color: ' + color"></button>
      </li>
    </ul>

    • Muchas gracias! Esto funciona muy bien! Gracias por el aviso sobre jQuery manipulación. Estoy usando la función de autocompletar en las filas específicas, así que no creo que pueda hacerlo a través de ko. Gran solución
    • el uso de la costumbre enlaces para la función de autocompletar padawan. 😛 una cosa que he aprendido después de 3 meses devving con ko: el uso personalizado de los enlaces con jquery/jquery ui cosas.
    • He trabajado con knock-out para las edades y no era consciente de que el parámetro de evento genial! gracias
  2. 20

    La $(event.de destino) solución es buena si está relacionada con un evento que ocurre en el cual el elemento del DOM elemento se encuentra en blanco. Pero a veces no tienen el elemento objetivo, porque no hay ningún evento (por ejemplo, desea desplazarse por una lista de un elemento que no fue un gesto por el usuario).

    En tal caso, se puede dar el elemento del DOM elemento atributo id de un valor único que contiene el id del artículo:

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

    y, a continuación, getDomObject() aspecto:

    getDomObject = function(item) { return $("#item_" + item.id); }
    • En mi humilde opinión, esta respuesta es mucho más completa para exactamente la razón por la yuvalr80 declaró.
    • Esta respuesta era lo que yo necesitaba, pero la aceptó respuesta es mejor para la pregunta original. Gracias por publicar esta respuesta también sin embargo, exactamente lo que necesitaba. No es una locura, sobre el cruce de las líneas de MVVM, pero yo sólo tenía una manera eficiente para desplazarse a un elemento en la vista, y no se siente como añadir un extra observables para cada objeto en mi lista para este.
    • Funciona, pero pasando el ID y, a continuación, obtener el DOM por que la ID. Rompe algunas reglas. Cualquier no-IDENTIFICACIÓN de la solución sería muy apreciada.
    • Estoy de acuerdo con Andrew Steitz – esto debe ser aceptado respuesta. Es mucho más integral de la solución.
    • Tener cuidado de no ejecutar el jQuery expresión antes de que el KO se produce el enlace, de lo contrario, el elemento DOM ID no se establece – he seguido este respuesta para agregar un afterBind() método.
  3. 7

    Que añadir una 3ª opción, también para los casos donde no se dispone de un evento a trabajar (si tienes un evento, el aceptado respuesta es mejor/optimizado).

    Crear un enlace personalizado, tales como:

    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);
            }
        }
    };

    uso es como sigue:

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

    En el caso anterior, $padre es mi Modelo de Vista. Tengo observa un objeto que contiene un IDENTIFICADOR único. En cualquier momento puedo establecer que desplázate() del objeto, la lista se desplaza a ese elemento.

    Nota que mi código asume que el DIV padre de la LI tiene la barra de desplazamiento (overflow:auto/scroll). Usted puede ajustar a sus necesidades, posiblemente el uso de una clase en la que el padre y el uso que de su selector de jQuery, o a hacer muy flexible podría pasar el selector a través de sus datos-opciones de enlace… para mí, esto era suficiente, ya que yo siempre uso de divs para mi desplazable secciones.

    • Yo he hecho algo similar y funciona bastante bien! Gracias por el post
  4. 5

    He tenido un problema similar. Se me ocurre una solución que se asemeja Backbone.js el uso de el y $el de referencia.

    en su ViewModel:

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

    en html (por ejemplo, el elemento de la lista):

    <!-- 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>

    en bindingHandlers (mostrando todos los argumentos posibles para 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());
      }
    };

    Por ejemplo, entonces usted puede utilizar $el como:

    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");
      }
    }

    Espero que esto ayude!

    • Deseo que puedas upvote esto varias veces, coz he necesitado esto varias veces y he venido a través de su respuesta varias veces!
  5. 4

    Mi solución (válido para el «valor» de unión)

     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);
    } 

    Ahora tienes yourobservable.$el y yourobservable.el que se unen para jquery y elemento de DOM.

Dejar respuesta

Please enter your comment!
Please enter your name here