2012-05-30 2 views
12

Как отключить и включить тег привязки с этой настраиваемой привязкой. Он отлично работает с элементами ввода, но тег привязки просто изменяет CSS, а не отключает.knockout.js и отключение тега привязки

<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

Я только видел якоря теги "отключен", установив их onlick в ложный. Что вы имеете в виду, что хотите, чтобы якорь «отключил» его? – Tyrsius

+0

Просто убедитесь, что он не запускает какие-либо события кликов, и когда включено, события кликов переименовываются. –

+1

В качестве альтернативы вы можете использовать логику комментариев KOs, чтобы просто создать другой тег. См. Http://stackoverflow.com/q/15969045/52551 –

ответ

11

Вам необходимо зафиксировать событие click в обработчике привязки.

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

Вот рабочий пример:

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

UPDATE 1: Если вам нужно, чтобы другие обработчики событий, связанные после придавалось Нокаут Обработчик связывания, вам нужно добавить stopImmediatePropagation в обработчик события вместе с preventDefault.

пример: http://jsfiddle.net/kp74u/55/

UPDATE 2: Если вы хотите отключить все обработчики событий (наряду с клик обработчиков событий, прикрепленных до вашего связывания обработчика, вам нужно «взломать» на события массив Jquery). Обратите внимание, что это не может работать и другие версии JQuery (пример использует 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 
      }; 
     }); 
    } 
}; 

пример: http://jsfiddle.net/nickolsky/kp74u/40/

UPDATE 3: Как уже было сказано там (suggested edit by FIR55TORM, извините не могу утверждать это полностью правильно править, потому что я слишком поздно, чтобы рассмотреть): если вы используете JQuery 1.10.x, вам нужно будет добавить подчеркивание для доступа к объекту «данными», как так:

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

Пересмотренный скрипка для JQuery 1.10.x: http://jsfiddle.net/nickolsky/kp74u/41/

+0

Остановляет ли это другие события кликов? http://jsfiddle.net/kp74u/3/ –

+0

Я добавил обновление об отключении всех событий click – Artem

+0

Начиная с jQuery 1.8, вы больше не можете обращаться к данным через этот API. Замените на 'jQuery._data (key, value)' –

1

Я нашел этот ответ, когда выпучив на способ сделать это, но мне не понравился подход так сделали мой собственный

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

Слаженным с нативной мыши и дает возможность связывание (отключить связывания не реализованные) скрипки (Fiddle также использует свою конвенцию над библиотекой конфигурации) http://jsfiddle.net/xCfQC/30/

+0

Действительно понравилась эта идея, основным недостатком является то, что вы должны определить метод «щелчка» для ее работы. См. Мой ответ для решения, где он работает с определенным кликом или без него. – Edyn

0

Используя @Anders ответ, как вдохновение, я придумал свою собственную версию этого. Позволяет использовать «включить», «отключить» с помощью «клика» или без него. Также допускается настраиваемый отключенный класс, в противном случае по умолчанию «отключен».

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

Невозможно действительно увидеть, когда вы хотите включить/отключить без обработчика кликов: D Вот версия, поддерживающая отключить http://jsfiddle.net/xCfQC/31/ – Anders

+1

@Anders Когда у вас есть якорь с набором href и no необходимо щелкнуть. Это была моя ситуация. – Edyn

+0

Но href все равно выполнит, его единственный css? Вам нужно вернуть false из обработчика кликов, чтобы он не срабатывал, вы могли бы исправить это в обработчике clikc обертки. – Anders

0

Это мой подход:

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; 
} 
Смежные вопросы