Mixing Knockout with jQuery
Asked Answered
P

2

4

I'm creating a commenting system with knockout.js and I'm having some issues with getting the templating working with our existing jQuery functions.

One example is with the dates comments are created. I wrote a jQuery function that causes the data to turn from 5-5-2012 to 2 Days ago. For example:

    <ul data-bind="foreach: Comments">
        <li data-bind="attr: { id: Id }" class="Comment">
           <div data-bind="text: DateCreated" class="prettyDate"></div>
           ...
        </li>
    </ul>


    <script type="text/javascript">
          $(function(){
              $(".prettyDate").prettify();
          });
    </script>

With this code, when I add a new comment dynamically, the date stays in the 5-5-2012 format. There are several other custom jQuery functions that act on repeating data that is now dynamically created by knockout (usually by selecting based on classes).

How can I apply these custom jQuery functions on dynamic data generated by knockout.js?

Percaline answered 9/5, 2012 at 1:57 Comment(3)
I wonder if monitoring DOM changes with something like .live worksFotheringhay
@TomWijsman - sadly, live has been deprecated in favor of .on api.jquery.com/live Also, I don't know what event I would bind to. What do you think a good event would be? I don't think load would work :/Percaline
Ah right, I see, haven't used it yet but just heard of it a while ago. You can find a list of events where you would be looking for the DOM ones; perhaps something about modification of the character data, I doubt if it would change the sub tree itself.Fotheringhay
F
4

One option might be to use a custom binding handler which sends bound elements through your jQuery plugin, e.g.:

http://jsfiddle.net/mikebridge/Q9r86/4/

Another possibility might be to add a computed observable in your view model.

Figureground answered 9/5, 2012 at 6:15 Comment(4)
Yeah, I was afraid of being forced to use custom bindings... Right now we are using a class to define who gets prettified. +1 for the good example! If I can't figure out anything else, I'll use this.Percaline
Hey, I used your idea and forked a new jsfiddle. This might be a little more closely related to my problem: jsfiddle.net/BGHhPPercaline
Hope it gets you at least part of the way there. I suspect the cleanest solution is to call it using a computed observable, because it would require less code to trigger the jquery transformation. I also thought there might be a jquery trigger like .live or .on which would detect dom insertion---that'd be cleaner---but I don't think there is one.Figureground
Yeah, I've been looking at the .on but so far I haven't gotten it to work :/Percaline
H
0

If you need to run some further custom logic on the generated DOM elements, you can use any of the afterRender/afterAdd/beforeRemove/beforeMove/afterMove callbacks described below.

<ul data-bind="foreach: { data: myItems, afterAdd: yellowFadeIn }">
    <li data-bind="text: $data"></li>
</ul>
<button data-bind="click: addItem">Add</button>


<script type="text/javascript">
    ko.applyBindings({
        myItems: ko.observableArray([ 'A', 'B', 'C' ]),
        yellowFadeIn: function(element, index, data) {
            $(element).filter("li")
                      .animate({ backgroundColor: 'yellow' }, 200)
                      .animate({ backgroundColor: 'white' }, 800);
        },
        addItem: function() { this.myItems.push('New item'); }
    });
</script>

Source: http://knockoutjs.com/documentation/foreach-binding.html#note-7-post-processing-or-animating-the-generated-dom-elements

However, beware of the following note:

If your goal is actually to attach other behaviors to new DOM elements when they have been added (e.g., event handlers, or to activate third-party UI controls), then your work will be much easier if you implement that new behavior as a custom binding instead

Hanzelin answered 20/2, 2015 at 14:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.