Conditional 'click' binding with Knockout

15,172

Solution 1

Do this

    <ul class="modal-subject-list" data-bind="foreach: filteredSubjects">
        <li data-bind="click: hasBeenAdded ? null : $parent.pickSubject">
            <!-- Lots of code here -->
        </li>
    </ul>

http://jsfiddle.net/7hcj6/

Read -

If the filteredSubject has been added, do nothing, else add to the list or whatever.

Solution 2

Just want to expand on @PW Kad's answer in case it helps others.

I found that I could apply a condition to the knockout event node so that all or none of the handlers are bound. In my case, I needed to bind events only to inputs that were not read only. So this does work if you need to do something similar. Happy coding.

event: $data.SomeProperty() ? null : { multiple event handlers }

Example Code:

<input type="number"
       data-bind="value: $data.Value,
                  css: $data.Css,
                  attr: {
                      title: $data.Title,
                      min: $data.Min,
                      max: $data.Max,
                      readonly: $data.ReadOnly
                  },
                  event: $data.ReadOnly() ? null : {  // <----- HERE
                      focus: $root.onFocus,
                      blur: $root.onBlur,
                      input: $root.onInput,
                      keypress: $root.onKeypress
                   }" />
Share:
15,172

Related videos on Youtube

RobVious
Author by

RobVious

Updated on June 11, 2022

Comments

  • RobVious
    RobVious almost 2 years

    I am binding the click event to every list item in a list:

            <ul class="modal-subject-list" data-bind="foreach: filteredSubjects">
                <li data-bind="click: $parent.pickSubject, css: {alreadyAddedBackground: hasBeenAdded}">
                    <!-- Lots of code here -->
                </li>
            </ul>
    

    I want to disable the click: binding if 'hasBeenAdded' resolves to true. I know some messy ways to take care of it:

    1. Have two list items, one for if: hasBeenAdded, and the other for if: !hasBeenAdded. This is far from DRY
    2. Handle this check with javascript and leave the view alone - I don't like this because unnecessary markup is being generated for list items that should be essentially disabled.

    Is there a way to register a "clickIf" binding?

  • Anders
    Anders over 10 years
    A button that does nothing when you click is hardly user friendly, better just to use the enable/disble binding
  • PW Kad
    PW Kad over 10 years
    OP was very specific in that he wanted to conditionally handle the click binding, whether he uses null or not in a production environment is his choice...
  • Kishor
    Kishor about 9 years
    it's better to replace "null" with function, <li data-bind="click: hasBeenAdded ? function() { return false; } : $parent.pickSubject">
  • Alexander Abakumov
    Alexander Abakumov about 9 years
    @Kishor, Could you please explain why it is better?
  • Zoltán Tamási
    Zoltán Tamási almost 8 years
    Be careful, using the function returning false has a completely different meaning. If there is null, knockout will not bind anything to the event. When you pass that kind of function, for example the default event will be prevented to say the least.
  • Zoltán Tamási
    Zoltán Tamási almost 8 years
    Also note, that knockout is not treating event bindings as computeds, which means that the first result which your expression evaluates to will be used by knockout for the whole lifetime. You cannot do something like this for example: data-bind="click: myObservable() ? null : myHandler" and expect that the handler will get bound and unbound based on the expression. This was kind of a surprise for me, but I guess it would add a big amount of complexity to implement properly.
  • zergski
    zergski over 2 years
    I'm not the biggest fan of that a large chunk of our application uses knockout at work, but you sir, showed me something that now seems so obvious. Thank you!

Related