I am trying to use knockout-sortable, with the mapping plugin, to drag a list of products to another list.
Here is a very stripped-back fiddle to try and show what I'm getting at.
What I want is for the products in the 'cart' to reference, not clone, the products on the 'shelf'.
I have managed to calculate the name of the items in the cart by referencing those on the shelf, but I am having trouble in getting the products in the cart to only have the data they need to make this reference, without all the other cruft.
Having looked around, I found this very tantalising solution by Ryan Niemeyer to a similar problem a couple of years ago, but the fiddles throw a 404 error!
I have created a 'clone' function, but because all my data is mapped it has not used a constructor such as:
var product = function(ID, name, other){
this.productID = ko.observable(ID);
//etc.
};
Which means that I cannot do what I want to do, which is:
product.prototype.clone = function(){
var x = ko.mapping.toJS(this);
delete x.productName;
delete x.someOtherData;
ko.mapping.fromJS(x);
};
Which I would hope would drop a new object into the cart with just a reference to the original productID
key. I have commented out the code for this in the fiddle. The console.log
does not get called after dragging, so the function is not even getting called.
I also looked on the Google forum for knockout-sortable and found this thread, which is where I got the clone bit from - but I can't make it fit my use case!
The result of a successful answer to this question will, when there is just a bike in the cart, leave productArray
as it is and have listArray
set to [{'productID':1}]
.
This is the first time that I've posted a question on SO, so please go easy on me if I have not made myself clear! I am already indebted to the community, as it has been so helpful in solving my problems for years and years :)
You would want your mapping options to look something like:
var options = {
productArray: {
create: function(mappingData) {
var result = ko.mapping.fromJS(mappingData.data);
result.clone = function() {
return { productID: result.productID() };
};
return result;
}
}
};
Alternatively, you could create a constructor for your product with a clone function on it and just return that like return new Product(mappingData.data);
I had the clone above just return the productID as a non-observable, which should be fine unless you need to react to that value changing.
The first line of your calculatedName
function would then need to be something like:
var x = ko.unwrap(arg.productID);
This will retrieve the value whether it is observable or not, so the function can work against the productArray or the listArray.