2012-02-27 11 views
14

Esta no es una situación ideal, pero debido a otro enlace de nocaut que estoy usando estoy en una situación en la que necesito que el elemento sea visible, si está ligado a algo.Obtener elemento que un observable está vinculado con Knockout?

¿Hay alguna manera de hacer esto?

== == Actualización

que no quería añadir cualquier contexto adicional en caso que se confunde la cuestión, pero como se puede obtener una respuesta más en línea con las expectativas Aquí está el panorama.

Estoy utilizando el enlace de validación no válida, que expone todos los errores utilizando el método ko.validation.group(model). Sin embargo, el problema es que solo le da los errores de texto, no le da ningún contexto en cuanto a qué parte del modelo le dio esos errores. Así que hice un pequeño cambio en la fuente para pasar ahora el observable vinculado a cada error, ya que esto puede ser útil para algunos escenarios, pero a partir de aquí tengo que ser capaz de vincular esto a un elemento para poder mostrar algunos validación en línea de algún tipo.

Knockout Validation proporciona una validación en línea muy básica donde crea un lapso después de su elemento y puede darle una clase, pero esto es demasiado básico para mis necesidades ya que actualmente estamos usando Qtip y otros sistemas de notificación para mostrar errores de validación, y debido a esto necesito poder tener un elemento Dom y un error. Hasta ahora tengo un error observable y un error, pero necesito vincular ese objeto observable (que podría ser cualquier propiedad ko.observable() del modelo) con su elemento DOM dado, si tiene un elemento vinculante.

Como todo lo que tengo es un objeto y estoy usando la validación impulsada desde el modelo y no desde la interfaz de usuario, el problema no se resolverá realmente a través de un enlace personalizado. Idealmente, debo ser capaz de descifrar el casamiento del objeto observable (un desconocido ko.observable()) con un elemento. No es demasiado específico del proyecto, pero mi proyecto actual resume la validación donde se activan los eventos (es decir, EventSystem.SendEvent(ValidationEvents.ValidationFailed, <element>, <error>)) luego un sistema de validación escucha estos eventos y vincula el error al elemento, ya sea una información sobre herramientas, un estilo de gruñido notificación, un cuadro de alerta, etc., así que estoy tratando de encontrar la mejor manera de mantener esta abstracción cuando se conduce la validación de los modelos no observables elementos DOM de la interfaz de usuario (es decir, jquery-ui)

== == 2 Editar

Me sorprendió un poco el hecho de que Knockout Validation sepa los elementos que los observables deben poner en sus propios elementos de validación, sin embargo, simplemente guardan el vacio existente. lue vinculante, por lo que voy a cambiar eso para agregar los elementos para cualquier elemento de validación basado en su método isValidatable(), al menos de esa manera para cada error puedo vincularlo a un observable, y para cualquier observables con enlaces de elementos que pueda vincular a los elementos, y si no hay ninguno, entonces está bien, serían errores de validación amplios. Voy a darle una oportunidad ya que esto debe ser algo similar (no probado aún):

if(utils.isValidatable(valueAccessor())) { 
    valueAccessor().extend({hasElementalBinding: true, elementalBinding: element}); 
} 
else { 
    valueAccessor().extend({hasElementalBinding: false}); 
} 

En torno a la línea 250 en la registerValueBindingHandler, voy a dejar esta cuestión abierta por un tiempo más largo en caso que alguien tiene una mejor solución .

+0

¿Pertinencia? http://stackoverflow.com/questions/8911544/how-to-get-the-elements-bound-to-a-model-in-knockoutjs –

+0

No realmente, es solo un enlace personalizado, estoy en un escenario donde Tengo acceso a un elemento observable, pero necesito agregar un nuevo elemento DOM y saber a qué elemento vincularlo. – Grofit

+0

Realmente creo que debería simplemente escribir su propio enlace de validación personalizado, porque entonces obtendrá un elemento y puede hacer con él lo que quiera. –

Respuesta

5

esto no va a ser muy rápido, así que me volvería a almacenar en caché los resultados, pero algo usando selectores de atributos de jQuery:

$('[data-bind*="Property"]') 

*= es el atributo contiene el selector: http://api.jquery.com/attribute-contains-selector/

Obviamente esto won' t atrapa todo lo que se suscribió manualmente usando el método .subscribe, pero no estoy seguro de cómo extraería los elementos de las funciones de todos modos.

Descargo de responsabilidad: Si bien esta solución probablemente funcionará, esto me parece una idea horrible, en su lugar escribiría un enlace personalizado (como se menciona en los comentarios) o encontraría alguna otra solución.

+1

¿Cómo puede obtener la propiedad en este ejemplo? Este es el quid de mi problema, tengo el objeto observable tan observable() me da su valor, pero podría ser 1 de 100 observables, así que necesito saber idealmente si hay alguna parte identificable de forma única del objeto observable que puedo usar para obtener el elemento dom, o incluso si está expuesto de alguna manera directamente desde el objeto observable, ya que debe usarlo debajo de las cubiertas. No quería contaminar la pregunta con más contexto de lo necesario, pero podría ser mejor explicar esto. – Grofit

+0

Ah, entonces la respuesta es no con los enlaces actuales. Pero podría escribir fácilmente un enlace personalizado para usar en lugar de valor o algo que expone su lista de elementos dom. –

+0

Puede ver en la fuente del enlace 'value', que en realidad no expone públicamente el elemento DOM: https://github.com/SteveSanderson/knockout/blob/master/src/binding/defaultBindings.js –

18

He hecho algo similar a lo que mencionaste anteriormente. Mi etiqueta-bind de datos incluye un enlace personalizado:

data-bind="... myvalidationbinding: myobservable" 

Luego, en mi manejador de unión extiendo lo observable

ko.bindingHandlers.myvalidationbinding = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) { 
    valueAccessor().extend({element: element }); 
    } 
}; 

Y finalmente mi extensión es

ko.extenders.element = function (target, element) { 
    target.DOMElement = element; 
} 

Ahora puedo suscribir isValid() dado por knockout.validation y si no es válido, obtenga el elemento al que se vincula el observable y luego manipúlelo con jQuery.

+3

¿Qué sucede si el observable está vinculado a más de un elemento? – Milimetric

+0

extendiendo la respuesta de Jon Keto para agregar elementos múltiples enlazados en el mismo observable: 'target.DOMElements = target.DOMElements || []; target.DOMElements.push (elemento); ' – vfportero

+2

+1 ¡Qué maravilloso extensor! No sé si es una buena práctica tener acceso al elemento DOM desde ViewModel, pero en mi caso, en este momento, el diseño es mucho más simple. – Samuel

Cuestiones relacionadas