2012-05-30 16 views
12

Jak można wyłączyć i włączyć znacznik zakotwiczenia z tym niestandardowym powiązaniem. Działa wspaniale z elementami wejściowymi, ale znacznik kotwicy zmienia tylko CSS, a nie wyłączenie.knockout.js i wyłączanie znacznika zakotwiczenia

<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

Widziałem tylko znaczniki zakotwiczenia "wyłączone", ustawiając ich do onlick fałszywy. Co to znaczy, że chcesz się z kotwicą "wyłączyć"? – Tyrsius

+0

Tylko po to, aby upewnić się, że nie uruchamia żadnych zdarzeń kliknięcia, a po włączeniu zdarzenia kliknięcia zostaną zmienione. –

+1

Jako alternatywę możesz użyć logiki komentarzy KOs, aby wytworzyć inny znacznik. Zobacz: http://stackoverflow.com/q/15969045/52551 –

Odpowiedz

11

Musisz przechwycić zdarzenie kliknięcia w uchwycie powiązania.

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

Oto przykład roboczych:

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

UPDATE 1: Jeśli chcesz, aby zapobiec inne programy obsługi zdarzeń związanych po nokaut obsługi wiążący został dołączony, trzeba dodać stopImmediatePropagation do obsługi zdarzeń wraz z preventDefault.

przykład: http://jsfiddle.net/kp74u/55/

UPDATE 2: Jeśli chcesz, aby wyłączyć wszystkie programy obsługi zdarzeń (wraz z dołączonymi obsługi zdarzeń kliknięcia przed obsługi wiążącego, trzeba „włamać” tablicę zdarzeń jquery). Należy pamiętać, że to nie może działać inne wersje jQuery (przykład używa 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 
      }; 
     }); 
    } 
}; 

przykład: http://jsfiddle.net/nickolsky/kp74u/40/

UPDATE 3: Jak wspomniano tam (suggested edit by FIR55TORM, przepraszam, nie może zatwierdzić ten całkowicie poprawna edycja, bo jestem zbyt późno na wakacje): jeśli używasz jQuery 1.10.x, trzeba będzie dodać do podkreślenia dostęp przedmiotem jest „dane” tak:

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

Revised skrzypce dla jQuery 1.10.x: http://jsfiddle.net/nickolsky/kp74u/41/

+0

Czy to powstrzymuje inne zdarzenia kliknięcia? http://jsfiddle.net/kp74u/3/ –

+0

Dodałem aktualizację dotyczącą wyłączania wszystkich zdarzeń kliknięcia. – Artem

+0

Od wersji jQuery 1.8 nie można już uzyskać dostępu do danych za pośrednictwem tego interfejsu API. Zamień na 'jQuery._data (klucz, wartość)' –

1

Znalazłem odpowiedź kiedy goggling na drodze robi to, ale nie podoba mi się podejście, tak jak mój własny

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

Jego szwu z natywnym kliknięcia i umożliwiają wiązanie (wyłączyć wiązania nie zaimplementowane) Fiddle (Fiddle wykorzystuje również moją konwencję nad biblioteką konfiguracji) http://jsfiddle.net/xCfQC/30/

+0

Podobał mi się ten pomysł, główną wadą jest zdefiniowanie metody "kliknięcia", która zadziała. Zobacz moją odpowiedź na rozwiązanie, w którym działa z lub bez zdefiniowanego kliknięcia. – Edyn

0

Korzystanie @Anders odpowiedzieć jako inspiracji, wymyśliłem własną wersję tego produktu. Pozwala na użycie "włącz", "wyłącz" z lub bez "kliknięcia". Pozwala także na niestandardową wyłączoną klasę, w przeciwnym razie domyślnie "wyłączone".

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

Cant naprawdę widzi usecase kiedy chcesz włączyć/wyłączyć bez obsługi kliknięcia: D Oto wersja obsługująca wyłączenie http://jsfiddle.net/xCfQC/31/ – Anders

+1

@Anders Kiedy masz kotwicę z ustawionym href i nie potrzeba kliknięcia. Taka była moja sytuacja. – Edyn

+0

Ale href nadal będzie wykonywał, tylko jego css? Musisz zwrócić wartość false z obsługi kliknięcia, aby nie uruchamiał się, możesz to naprawić w opakowaniu clikc. – Anders

0

To jest moje podejście:

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; 
} 
Powiązane problemy