I want to create a number of div
s that I can move and resize, and bind their width
, height
, etc. to an object in an array. So, if I create six divs, I have six objects in my array, each object having .width
, .height
, etc.
I don't quite understand how I would bind the input and span text to the array object properties using knockout.js. Here's my attempt:
var counter = 0;
var objects = [];
$(document).ready(function () {
dostuff($("#main")); // give it a target container div
});
function dostuff(target) {
counter++;
// create a div containing a span and an input that binds to knockout.js
target.append('<div id="d' + counter + '">width:<span id="d' + counter +
'" data-bind="text:objects[' + counter + '].width"></span>' +
'<input type="text" id="d' + counter +
'" data-bind="value:objects[' + counter + '].width"/></div>');
var a = $("#d" + counter);
a.css("position", "absolute");
a.css("width", "100px");
a.css("height", "100px");
a.css("background-color", "#" +
Math.ceil(Math.random()*9) + "0" +
Math.ceil(Math.random()*9) + "0" +
Math.ceil(Math.random()*9) + "0");
a.resizable({
stop: function (e, ui) {
this.childNodes[2].value = ui.size.width;
}
});
objects[counter] = { width: "100px", height: "100px",
top: "0px", left: "0px" };
ko.applyBindings(objects[counter]);
}
How would I get the objects[1].width
to bind to the div d1's <input>
value?
The minimal amount of changes that you would have to make to get this to happen would be doing something like:
target.append('<div id="d' + counter + '" data-bind="style: { width: width , height: height, top: top, left: left } }">width:<span id="d' + counter +
'" data-bind="text: width"></span>' +
'<input type="text" id="d' + counter +
'" data-bind="value: width"/></div>');
So, this uses the style
binding on your main div. Also, since you are calling applyBindings on objects[counter] you can reference the properties directly in the bindings (rather than through objects[counter]).
If you are calling this function multiple times, then you will want to be careful with how you call ko.applyBindings
. If you do not pass a second parameter, then it will apply to the entire document. You really only want to do that one time. In your case, you would likely want to pass a second parameter to indicate the exact root element to start with. So, you would call something like ko.applyBindings(objects[counter], $("#d" + counter)[0]);
I don't know of your exact use case, but if it was me, I would create my array of objects first and then use a template to build the divs. Then, in the markup I would have a container that calls the template
binding with the foreach
option passing the array. Then, you would create a template that contains the markup for each div. This way you can avoid building the markup as strings. If you want an example of doing something like that, let me know.
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With