rniemeyer / knockout-sortable

A Knockout.js binding to connect observableArrays with jQuery UI sortable functionality
MIT License
547 stars 128 forks source link

new feature request - add targetParentNode to args #87

Open pilavdzic opened 10 years ago

pilavdzic commented 10 years ago

It would be very useful to have the targetParentNode.

Any way you can add this to args?

For example I have a bunch of sortable lists I am using on an admin screen. By dragging and dropping between them I want to create many to many relationships between database tables. For example on the left I have a bunch of Award sortable lists and on the Right a bunch of Task sortable lists. I want to create a AwardTask link record, which needs to contain the awardID and the taskID.

My DOM elements for each sortable already contain the awardID, so if I could simply access targetParentNode, I could get a hold of the ID of each sortable list.

Thanks!

rniemeyer commented 10 years ago

just answered this on SO: http://stackoverflow.com/questions/21995159/knockoutjs-sortable-binding-how-to-get-targetparentnode. Let me know if you still have issues. I would be happy to help you find a suitable solution. Thanks!

pilavdzic commented 10 years ago

Thanks, but this means each time I refresh data from the server I would need to loop through all the observablearrays and inject things or subscribe to each array. Is there any easy/simple way to attach a subscription to every item in an array each time ko.mapping.fromJS is called?

Wouldn't it yield much nicer/cleaner code if args had an argument that pointed to the DOM node of the target observableArray somehow? One can always use the DOM node to to get it's parent, and ko.ContextFor to get the observable associated with it, so having access to the DOM node is key, with that you can get anything else you need.

rniemeyer commented 10 years ago

I didn't realize that you were using the mapping plugin. You can use the mapping options and provid e a create or update callback to control how it behaves. Here is a sample of attaching an id to an observableArray in the create callback: http://jsfiddle.net/rniemeyer/tBFPv/

As an alternative, here is an example of using .bind with an afterMove function to fix the specific name/id as the first argument: http://jsfiddle.net/rniemeyer/hUC76/.

You do have access to the event and ui arguments as the second and third args to the callbacks, if you want to look at the DOM in your code. My preference is to restrict DOM related code to custom bindings and do these things in the view model, but I do understand that using something like the mapping plugin can make it harder to easily control the vm layer.

pilavdzic commented 10 years ago

My app has complex data structures and even includes a web based frontend for data warehouse style reporting so I am having all sorts of trouble with the mapping plugin...

For example, I need to update only one part of my viewModel. The following seems to work, but can't escape the feeling I might not be doing this correctly, does this look right to you?

                  if (typeof vm.Sections=== 'undefined') 
                      vm.Sections= ko.mapping.fromJS(ajaxResponseModel);
                  else
                      ko.mapping.fromJS(ajaxResponseModel, {}, vm.Sections);

//durandal calls activate() again if you leave the page then come back to it (that's ok we probably want to refresh this data in that case) but only calls ko.applybindings once (which makes it very easy for things to get in a messed up state - its not obvious anything is wrong when new observables get created after applybindings was called so they are now no longer bound, but some old ones are).

The mapping plugin also doesn't seem to let me apply options to only one level of a hierarchy or one part of a viewmodel. So when you have a large data structure and some items may be named the same things, I need to change static models in c# on the server and break server side naming conventions just to make the mapping plugin be able to deal with my models.

It also does not seem to have a setting to turn everything into an observable, only the leaves, so I run into errors like something() is not a function every once in a while and I have to go back and manually turn things into an observable.

My data structure is very complex but the amount of data that applies to a given user is very small so I am not having any performance issues I just want everything to be observable.

Do you ever run into such issues or what do you use instead of the ko.mapping plugin?

Thanks!