We were unable to load Disqus. If you are a moderator please see our troubleshooting guide.
Fantastic stuff Ryan :-)
Hi Ryan.
I am building a survey maker using your plugin.
It is a hierarchy in structure (nodes can be dragged between branched but not change in depth).
http://jsfiddle.net/VgrAD/3/
(The green boxes are the drag handles)
Things are working well apart from one problem.
When I add a new page, I can drag that page to where I want, however I cannot drag categories into the new page (Categories can be dragged between existing pages).
Before using your sortable plug-in I was calling the Jquery sortable directly and then recalling sortable() as needed when new items were added and it was working as intended.
Is there any way I can “refresh” the items in the sortables etc?
Thanks for your help. Great work by the way.
Sam
@Sam - from my testing it looks like the issue is that the new "categories" div has no height. Same with trying to add existing questions to a new category. Seems like it works properly if you just add: .categories { min-height: 100px; } and .questions { min-height: 100px; }. Let me know if I got your issue wrong or if this does not work for you.
One other tip: if you want to avoid having to add "options: { handle: '.drag-handle' }" on each sortable, then you can set it globally by doing: ko.bindingHandlers.sortable.options = { handle: '.drag-handle' };
Do that prior to calling applyBindings.
I really like this Ryan. great example.
@Ryan, thanks for your feed back, works perfectly now.
Sam
great stuff Ryan, i am thankful
Hi Ryan. This is great. However, if I hit F12 in IE9 and change to IE8 mode, the drag and drop no longer works correctly. The first item dragged disappears and subsequent drags and drops don't always update the underlying model. Any ideas?
@Anonymous - There is an issue logged for it here: http://github.com/rniemeyer...
There is an oddity in the way that jQuery's .data is working in IE8. I have a beat on how to fix it and should be able to commit a fix tonight. Will post an update here when the fix is in.
@Anonymous - I made the fix and it is available now.
Superb. Thanks!
Ryan, this is a great knockout plugin! To anyone trying to figure out how to pass extra options into the jQuery UI sortable, you do it like this:
data-bind="sortable: { data: datasource, options: { axis: 'y' } }"
Thanks for hard work!
R.
hi,
I had use same for
data-bind="sortable: { data: datasource,options: { appendTo: document.body }}"
but with no luck. Anybody can help?
Ran Your syntax looks correct to me. Anything inside of "options" gets passed on when initializing the "sortable". Maybe you can put something in jsFiddle that shows your problem?
thanks for reply.
Heres the example http://jsfiddle.net/bHRSW/1/
What I want to do is move the items across the panels. ( As you can see I have used jQuery Layout plug-in)
@Ran sorry that I missed this earlier. The options are being passed to the sortable plugin, but it looks like you also need to add "helper: 'clone'" in the options. Here is an updated sample where I add the options globally (line right before applyBindings): http://jsfiddle.net/rniemey...
Wow... that's fantastic. thank you very much.
Ryan,
Just wanted to thank you for single-handedly making Knockoutjs the best documented library of it's kind. Knockoutjs.com is amazing and getting you started, but your JSFiddle examples take it to the next level and beyond. Thanks again on behalf of the everyone* who benefits from your work.
* A really big number of developers
Hi guys,
I added a display order attribute to each of the moveable items. What is the best way to update the display order of that item and update the display orders of every other item in the list.
For example he following jsfiddle http://jsfiddle.net/rayray/... is updated with a display order
Here is my preferred way to keep track of an index on an observableArray. It uses an extender to subscribe to changes to the observableArray and keep an observable updated on the item with its index. In this case you can pass in the name of the property to the extender ("displayorder"). If you did not want it to be 0 based, then you could add 1 in the extender. http://jsfiddle.net/rniemey...
Hi Ryan,
Thanks for this solution. Works really well.
Ray
Top notch. Big, big thank you!
Hi Ryan,
I've found a bug in the Seating example:
http://jsfiddle.net/rniemey...
If you try to move the 'Chase' from the 2nd table to the first
and then
move 'Erin' from the 2nd table to the first again,
'Chase' disappears from the 2nd table in the Seating Assignment but not in the Master Array.
Would you know why is this?
Cheers,
GianPaJ
@GianPaJ - hello! It is related to the issue logged here: https://github.com/rniemeye.... I am looking at some options to handle it and am trying to avoid re-rendering the whole list. Hope to have it fixed soon!
An option at the moment is to make sure that your templates have no text nodes (line feeds). Here is the fiddle with the line feeds removed from the anonymous templates: http://jsfiddle.net/rniemey...
Wow that was fast!
Very weird for me though that some empty lines would do such a thing :P
Thanks!
Thanks for a great binding Ryan. Helped me a lot to make the work done really fast.
I'm writing some tool using the knockout.js and signalr that uses your binding so it was really helpfull. You can find some first info about it at
http://software-workshop.eu...
if you are interested. Thanks again!
@Ryan
I'm trying to implement a version of the drag-drop functionality of the Seating chart for a many todo lists.
I'd like to have only todo list names on their own, and then be able to drag and drop into the title of a todo list (make them droppable).
I've managed to make it work. But i was wondering if there is a way to not having the 'sorting' binding looping through the array.
What i'm trying to do is to add some html inside the div with data-bind="sorting: {...}".
something like this:
https://gist.github.com/203...
@Gianfranco - Hello- I'm not sure that I am quite getting what you are after yet. Can we try to get a fiddle going? Can you make this one closer to what you are after? http://jsfiddle.net/rniemey...
I guess what i'm trying to do is something like this:
http://jqueryui.com/demos/s...
using ko.sortable
and adding some icons on the tabs
http://jsfiddle.net/U3a8K/1/
Thanks a lot
How about something like: http://jsfiddle.net/rniemey...
I would like a droppable area or div where i can put other html but not loop through the array.
Also in my app I get this error:
Uncaught TypeError: Object [object Object] has no method 'remove'
Is that because my objects might not be ko.observable ?
.remove is a function of an observableArray. It sounds like you are maybe trying to call it on a normal array.
Here is an updated sample: http://jsfiddle.net/rniemey.... It is a little more complex than I would like, but basically it allows you to render a template for the drop area using an afterRender callback.
I will have to put some more thought into how the plugin could make this easier.
Cool. that is better than having another container just to be able to drag items into that inner array.
Just a quick question in this:
http://jsfiddle.net/U3a8K/4/
Why is that when you drag available items to the top (without releasing the mouse) it's trying to add an < li>.
But when using the items from the same array it doesn't?
is that suppose to happen right?
It looks like if you add a placeholder class, then it will use it rather than the default styling and this makes it so the li does not have a height.
Here is a sample of adding the placeholder globally through ko.bindingHandlers.sortable.options. http://jsfiddle.net/rniemey...
Great binding. I am now using it, thanks!
But I have one question - if you click on one item, edit it, then click on the next item to edit that, it flickers out of the second one you selected and you then need to click again to get it reenter the second textbox. Any ideas how I can make that work a bit smoother?
Also, in the example if you delete all the text out of an item it you can no longer click on to enter text back into it again. I made it test for blank items and remove them automatically and that works great, just thought I'd mention it to you in case you want to make that a default functionality.
@Enis - thanks for pointing that out. I hadn't really consider that aspect of it in much detail (mainly looking at sorting). I updated both of the fiddles to account for both of the things that you mentioned. Thanks!
Hey Ryan,
This is beautiful.
I have been trying to get simple Drag and Drop across lists (not sorting) working with various sample code that you (http://jsfiddle.net/rniemey... and others have posted.
Although I can hack it together a solution, there doesn't seem to be a 'robust' (or even working) version out there (even that fiddle has some issues). It seems like most 'drag and drop' is really a sorting solution as well.
Is there a way to use the sortable extension you created with drag and drop only (and not allow sorting within a list)? That is, I would like to turn off the ability to sort within a list, but still be able to drag the item over to another list (using helper:clone, for instance).
I am currently trying to create a version based off of http://pastie.org/1446229, but that seems (and is stated to be) very hacky (requiring global namespace access, rather than context specific).
The same with this set of articles (http://wilsonhut.wordpress..... Do we really need global _dragged, etc...?
If you have some clean ways of doing .drag / .drop bindings, being able to extend with .drop with options for acceptable types would be nice.
Anyway, thank you much for your outstanding work on knockout!
@Anonymous - The sortable binding won't work great for your scenario, unless you create a bunch of single item observableArrays.
If I was going to do drag/drop. I would probably start with something basic like: http://jsfiddle.net/rniemey.... The drag bindings job is to set meta-data on the element (the data) and initialize draggable. The drop bindings job is to execute a function and pass the data as read from the meta-data of the dropped item as the first argument.
Would be happy to help you further, if this doesn't quite match your scenario.
Hi Ryan, I was trying to do something similar, http://jsfiddle.net/cheersp..., where you can drag from a list of possible tasks, so that you can have them in both the high and normal priority lists.
I appreciate that this thread is old now, but if you have a moment to look at the fiddle I would really appreciate any feedback. I tried a couple of things I thought would work, like using foreach with $index in the template, and draggable with possibleTasks[0], and sortable with helper: 'clone' - but none of them worked!
Now I'm going to look at extending the fiddle you did for Anonymous, above, three years ago - but I have to be honest; those custom binding handlers are more than a bit over my head! It's all good learning though :)
Cheers,
Philip
EDIT: I'm getting closer! I have the basic functionality now, thanks to the forums, but I'm getting kooky display errors :( http://jsfiddle.net/cheersp...
EDIT2: I did it! thanks to reading this post: https://groups.google.com/d... The completed fiddle looks like this: http://jsfiddle.net/cheersp...
Thanks so much for posting your code! It is lovely code :)
That is exactly what I was looking for! You are so prolific and helpful it makes me want to cry. ;-)
And all that in like 8 lines of code!
It is so intimidating coming to this world of JavaScript and libraries. I am never quite sure where one library ends and another begins. Using jQuery for data setting, and ko for callbacks. And even more frustrating is looking at the production level bindings you put out (sortable) and seeing all the 'extra' code around extensions, etc... vs the simplicity here.
Knowing the JS environment is so crucial, and seems so untouchable when you just dabble in UI and are trying to get things done. The hard part as a 20 year OS engineer is seeing notes like this (from http://wilsonhut.wordpress....
"I could have stuck it in the data of the html element being dragged (that is: $(element).data(“key”, “value”))...
I wouldn’t leave data lying around tied to DOM elements or have to worry about **> cleaning them up. <**"
Again, I spent my life managing memory, and when I see a statement like that I shutter. I worry! He presents a general problem, but not specific enough for me to get the solution ('hanging around?'). Anyway, it kills me to not know how this stuff works. (And I am not blaming him at all, just my frustration with the complexities here. His notes were very helpful).
I need to sit on the beach for a year, with a lot of JS code and start figuring this stuff out. In the meantime, you and Steve have really blessed this community with your time and efforts. I wish the best for you!
Hey Ryan,
Can't seem to pass any templateOptions.
http://jsfiddle.net/johnsto...
Any help would be great. Cheers.
Hi Ryan,
This is great, we are already using this in our project. But now we see the problem while dragging in the empty list. In my project what I want it when I drag, one property of my dragged object will take the property of the list in which it is dragged into. I have tried to replicate my scenario in following jsfiddle. To explain you in brief, the list has cards. The list has listId. When the card is dragged in the card's listId now shud become new list's ListId.The code works fine in all scenarios.. but not when the list was initially empty. While using var toList = event.targetParent(); knockout-sortable.js throws error stating there is no parent only when the list is empty.This is my jsfiddle
http://jsfiddle.net/kunjank...
Please have a look and suggest the solution.
my new jsfiddle with the snippet where i assign the listID to the card ...
http://jsfiddle.net/kunjank...
thanks
Kunjan
@Anonymous - So, templateOptions only work with jQuery Templates. They do not work with KO's native template engine (not just in this binding, but in general). I just committed a change to pass on templateOptions though, so you could use it with jQuery Templates like: http://jsfiddle.net/rniemey.... I had to clear my cache to get the updated script in the fiddle for some reason. If you are not using jQuery Templates, then you would have to put your header into your view model and reference it using $parent/$root. Here is a sample: http://jsfiddle.net/rniemey....
Hope this helps!
@kunjan - here is how I would do it: http://jsfiddle.net/rniemey...
A few changes:
-the Cards arrays need to be observableArrays for the plugin
-Since the source and target observableArrays are available in the callbacks, I went through and added the appropriate ListId to each, so that there is no lookup (looping) necessary
-if your ListId in your real code is observable, then you would need to write it as an observable in the callback (arg.item.ListId(arg.targetParent.ListId)
-in the fiddle you were using ViewModel.myDropCallBack directly rather than from an instance of the view model. Probably wasn't happening in your real code.
Hope this helps. Here is the link again: http://jsfiddle.net/rniemey...
this has definitely done the work.. it solves my problem.. thanks so much..still dont understand although completely.. :-) thanks a lot.. Kunjan
@Kunjan - this basically takes advantage of the fact that observableArrays are functions (which are objects). So, we can actually add properties to the observableArray itself. Since, you have the source and target observableArrays available to you in the callbacks, this is an easy way to get the meta-data that you need to tag your cards with the new id. Hope that helps!
hi again.. here is my jsfiddle http://jsfiddle.net/kunjank... you have seen this before. when i see your examples above the drag and drop are very smooth. but in my application my drag and drop is not very smooth, literally have to wait and push kinda to make a place for this new item in the list. plz see this fiddle and let me know where i am going wrong.
Kunjan
one more hiccup in this.. I have a a link on each of the items in this lists.. it opens an overlay on click of this link. when I scroll down using mouse on overlay it starts dragging the items behind the overlay.. i want to stop drag in these lists when overlay is open.. how do i achieve this?
I have taken your teaching from this site to create another example. Since I am still learning it is not working the way I want. I have two tables with check boxes on each row. User will check the checkboxs for the rows s/he wants to move. The first fiddle I was able to get the display of the data correctly.
http://jsfiddle.net/3gbBm/
On the second fiddle I wrote the code to do the actual move of the rows. I have made some mistake/s such that the rows do not even display.
http://jsfiddle.net/8UM29/
I am not sure when using ko.mapping.fromJS(data) what is the correct way to add a method to the viewModel. Your site has been amazing for getting a better understanding of arrays.
Very nice addon! Always a pleasure to read your articles.
Thanks