2012-05-30 17 views
12

Come disabilitare e abilitare un tag di ancoraggio con questa associazione personalizzata. Funziona alla grande con gli elementi di input, ma il tag anchor cambia semplicemente il CSS, non la disabilitazione.knockout.js e disabilitazione tag di ancoraggio

<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

ho visto solo i tag di ancoraggio "disabile" impostando la loro onlick a falsa. Cosa vuoi dire che vuoi arrivare all'ancora per "disattivarlo"? – Tyrsius

+0

Giusto per assicurarsi che non attivi alcun evento di clic e, una volta abilitato, gli eventi di clic siano stati rinominati. –

+1

In alternativa, è possibile utilizzare la logica di commento di KO per produrre solo un tag diverso. Vedi: http://stackoverflow.com/q/15969045/52551 –

risposta

11

È necessario acquisire l'evento click nel gestore binding.

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

Ecco un esempio di lavoro:

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

UPDATE 1: Se è necessario evitare che altri gestori di eventi legati dopo ko gestore di legame è stato attaccato, è necessario aggiungere stopImmediatePropagation al gestore di eventi con preventDefault.

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

UPDATE 2: Se si desidera disattivare tutti i gestori di eventi (insieme a gestori di eventi click attaccati prima del tuo gestore vincolante, è necessario 'hackerare' il jquery eventi array). Si prega di notare che questo non può funzionare altre versioni di jQuery (esempio utilizza 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 
      }; 
     }); 
    } 
}; 

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

UPDATE 3: Come è stato detto lì (suggested edit by FIR55TORM, mi dispiace non può approvare questo completamente corretta modifica perché sono troppo tardi per rivedere): se si sta utilizzando jQuery 1.10.x, è necessario aggiungere una sottolineatura per accedere all'oggetto dei 'dati' in questo modo:

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

Revised violino per jQuery 1.10.x: http://jsfiddle.net/nickolsky/kp74u/41/

+0

Si fermano altri eventi click? http://jsfiddle.net/kp74u/3/ –

+0

Ho aggiunto l'aggiornamento sulla disabilitazione di tutti gli eventi click – Artem

+0

A partire da jQuery 1.8 non è più possibile accedere ai dati tramite tale API. Sostituisci con 'jQuery._data (chiave, valore)' –

1

ho trovato questa risposta quando goggling di un modo di fare questo, ma non mi è piaciuto l'approccio così ha fatto il mio

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

sua senza soluzione di continuità con il nativo click e attivare vincolante (disabilitare vincolante non implementato) Fiddle (violino utilizza anche la mia Convenzione oltre libreria di configurazione) http://jsfiddle.net/xCfQC/30/

+0

Questa idea mi è piaciuta molto, lo svantaggio principale è che devi definire un metodo di "clic" perché funzioni. Vedere la mia risposta per una soluzione in cui funziona con o senza il clic definito. – Edyn

0

Utilizzando @Anders risposta come ispirazione, mi si avvicinò con la mia versione di questo. Consente l'uso di "abilita", "disabilita" con o senza il "clic". Consente anche una classe disabilitata personalizzata, altrimenti il ​​valore predefinito è "disabilitato".

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

Non riesco a vedere l'usecase quando vuoi abilitare/disabilitare senza un gestore di clic: D Ecco una versione che supporta la disabilitazione http://jsfiddle.net/xCfQC/31/ – Anders

+1

@Anders Quando hai un'ancora con un set href e no bisogno di clic. Questa era la mia situazione. – Edyn

+0

Ma l'href continuerà ad essere eseguito, è il suo unico css? È necessario restituire false dal gestore di clic per non attivarlo, è possibile correggerlo nel wrapper clikc handler – Anders

0

Questo è il mio approccio:

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; 
} 
Problemi correlati