2012-05-30 15 views
12

¿Cómo puedo desactivar y habilitar una etiqueta de anclaje con este enlace personalizado? Funciona muy bien con los elementos de entrada, pero la etiqueta de anclaje simplemente cambia el CSS, no la desactivación.knockout.js y deshabilitar la etiqueta de ancla

<a href="link" data-bind="myDisabled: !enabled()"/> 

ko.bindingHandlers.myDisabled = { 
    update: function(element, valueAccessor) { 
     var value = ko.utils.unwrapObservable(valueAccessor()); 
     ko.bindingHandlers.css.update(element, function() {return { disabled: value }; }); 
     ko.bindingHandlers.disable.update(element, valueAccessor); 
    } 
}; 
+0

Sólo he visto etiquetas de anclaje "desactivado" configurando sus onlick a falso. ¿Qué es lo que quiere decir querer pasarle al anclaje para "desactivarlo"? – Tyrsius

+0

Solo para asegurarse de que no activa ningún evento de clic, y cuando está habilitado, los eventos de clic se reniervan. –

+1

Como alternativa, puede usar la lógica de comentarios de KO para producir una etiqueta diferente. Consulte: http://stackoverflow.com/q/15969045/52551 –

Respuesta

11

Debe capturar el evento click en su controlador de enlace.

HTML:

<a href="link" data-bind="disableClick: !enabled()">test</a> 
<br/><br/><br/> 
<input type="checkbox" data-bind="checked: enabled"> enabled ​ 

JavaScript:

ko.bindingHandlers.disableClick = { 
    init: function (element, valueAccessor) { 

     $(element).click(function(evt) { 
      if(valueAccessor()) 
       evt.preventDefault(); 
     }); 

    }, 

    update: function(element, valueAccessor) {   
     var value = ko.utils.unwrapObservable(valueAccessor()); 
     ko.bindingHandlers.css.update(element, function() {return { disabled_anchor: value }; }); 
    } 
}; 

ko.applyBindings({ enabled: ko.observable(false)}); 

Aquí está un ejemplo de trabajo:

http://jsfiddle.net/kp74u/54/

ACTUALIZA 1: Si tiene que evitar que otros controladores de eventos consolidados después se adjuntó manejador de unión nocaut, es necesario agregar stopImmediatePropagation al controlador de eventos junto con preventDefault.

ejemplo: http://jsfiddle.net/kp74u/55/

ACTUALIZACIÓN 2: Si desea desactivar todos los controladores de eventos (junto con los controladores de eventos de clic adjuntas antes de su controlador de la unión, es necesario 'hackear' la serie de eventos de jQuery). Tenga en cuenta que esto puede no funcionar otras versiones de jQuery (ejemplo utiliza 1,7):

ko.bindingHandlers.disableClick = { 
    init: function(element, valueAccessor) { 

     $(element).click(function(evt) { 
      alert('test before'); 
     }); 

     $(element).click(function(evt) { 
      if (valueAccessor()) { 
       evt.preventDefault(); 
       evt.stopImmediatePropagation(); 
      } 
     }); 

     //begin of 'hack' to move our 'disable' event handler to top of the stack 
     var events = $.data(element, "events"); 
     console.log(events); 
     var handlers = events['click']; 

     if (handlers.length == 1) { 
      return; 
     } 

     handlers.splice(0, 0, handlers.pop()); 
     //end of 'hack' to move our 'disable' event handler to top of the stack 


     $(element).click(function(evt) { 
      alert('test after'); 
     }); 
    }, 

    update: function(element, valueAccessor) { 
     var value = ko.utils.unwrapObservable(valueAccessor()); 
     ko.bindingHandlers.css.update(element, function() { 
      return { 
       disabled_anchor: value 
      }; 
     }); 
    } 
}; 

ejemplo: http://jsfiddle.net/nickolsky/kp74u/40/

ACTUALIZACIÓN 3: Como se mencionó allí (suggested edit by FIR55TORM, lo siento no puede aprobar esta completamente correcta edición porque soy demasiado tarde para revisar): si está usando jQuery 1.10.x, tendrá que añadir un guión para tener acceso a los objetos de datos '', así:

var events = $._data(element, "events"); 

Revisado violín para jQuery 1.10.x: http://jsfiddle.net/nickolsky/kp74u/41/

+0

¿Esto detiene otros eventos de clic? http://jsfiddle.net/kp74u/3/ –

+0

Agregué la actualización sobre la desactivación de todos los eventos de clic – Artem

+0

A partir de jQuery 1.8 ya no se puede acceder a los datos a través de esa API. Reemplazar con 'jQuery._data (clave, valor)' –

1

encontré esta respuesta cuando goggling una manera de hacer esto, pero no me gusta el enfoque lo hizo mi propia

var orgClickInit = ko.bindingHandlers.click.init; 
ko.bindingHandlers.click.init = function (element, valueAccessor, allBindingsAccessor, viewModel) { 
    if (element.tagName === "A" && allBindingsAccessor().enable != null) { 
     var disabled = ko.computed(function() { 
      return ko.utils.unwrapObservable(allBindingsAccessor().enable) === false; 
     }); 
     ko.applyBindingsToNode(element, { css: { disabled: disabled} }); 
     var handler = valueAccessor(); 
     valueAccessor = function() { 
      return function() { 
       if (ko.utils.unwrapObservable(allBindingsAccessor().enable)) { 
        handler.apply(this, arguments); 
       } 
      } 
     }; 

    } 
    orgClickInit(element, valueAccessor, allBindingsAccessor, viewModel); 
}; 

Su perfecta con el clic nativa y permitir la unión (desactivar unión no implementado) violín (violín también utiliza mi Convención sobre biblioteca de configuración) http://jsfiddle.net/xCfQC/30/

+0

Realmente me gustó esta idea, el principal inconveniente es que debe definir un método de "clic" para que funcione. Vea mi respuesta para una solución donde funciona con o sin clic definido. – Edyn

0

Usando @Anders responden como fuente de inspiración, me ocurrió con mi propia versión de este. Permite el uso de "habilitar", "desactivar" con o sin el "clic". También permite una clase personalizada deshabilitada, de lo contrario se predetermina a "deshabilitado".

var koEnableUpdateOrig = ko.bindingHandlers.enable.update; 
ko.bindingHandlers.enable.update = function (element, valueAccessor, allBindings) { 
    // call original enable update 
    var result = koEnableUpdateOrig.apply(this, arguments); 
    var enabled = ko.unwrap(valueAccessor()); 

    // get and apply disabled class 
    var disabledClass = "disabled"; 
    if (allBindings) 
     disabledClass = allBindings().disabledClass || "disabled"; 
    if (enabled) { 
     $(element).removeClass(disabledClass); 
     if (element.tagName === "A") 
      $(element).off("click.koEnableUpdate"); 
    } 
    else { 
     $(element).addClass(disabledClass); 
     if (element.tagName === "A") 
      $(element).on("click.koEnableUpdate", function (e) { e.preventDefault(); }); 
    } 

    return result; 
}; 
ko.bindingHandlers.disable.update = function (element, valueAccessor, allBindings) { 
    // call enable with the reverse value 
    // the original knockout disable does this, but does not pass the allBindings 
    ko.bindingHandlers.enable.update(element, function() { 
     return !ko.unwrap(valueAccessor()) 
    }, allBindings); 
}; 

var koClickInitOrig = ko.bindingHandlers.click.init; 
ko.bindingHandlers.click.init = function (element, valueAccessor, allBindings) { 
    // wrap click function with enable/disable check 
    var valueAccessorOrig = valueAccessor(); 
    valueAccessor = function() { 
     return function() { 
      if (ko.unwrap(allBindings().enable) || 
       (allBindings().disable == null || !ko.unwrap(allBindings().disable))) { 
       valueAccessorOrig.apply(this, arguments); 
      } 
     } 
    }; 

    // apply wrapped click to original click init 
    koClickInitOrig.apply(this, arguments); 
}; 
+0

No puedo ver realmente el uso cuando desea habilitar/deshabilitar sin un controlador de clic: D Aquí hay una versión que admite deshabilitar http://jsfiddle.net/xCfQC/31/ – Anders

+1

@Anders Cuando tiene un ancla con un conjunto de href y sin necesidad de hacer clic. Esa era mi situación. – Edyn

+0

Pero el href todavía se ejecutará, ¿es solo css? Debe devolver falso desde el controlador de clics para que no se dispare, puede corregirlo en su controlador clikc de contenedor – Anders

0

Este es mi enfoque:

JavaScript

(function() { 
    var originalDisableUpdate = ko.bindingHandlers.disable.update; 

    ko.bindingHandlers.disable.update = function (element, valueAccessor) { 
     if (element.tagName === 'A') { 
     var 
      value = ko.utils.unwrapObservable(valueAccessor()), 
      disabled = 'disabled'; 

     if (value) { 
      element.setAttribute(disabled, null); 
     } 
     else { 
      element.removeAttribute(disabled); 
     } 
     } 
     else { 
     originalDisableUpdate(element, valueAccessor); 
     } 
    }; 
})(); 

CSS

a[disabled] { 
    pointer-events:none; 
    cursor:default; 
} 
Cuestiones relacionadas