Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind a div width/height to form fields?

I want to create a number of divs 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?

like image 590
Zachary Scott Avatar asked Oct 11 '22 08:10

Zachary Scott


1 Answers

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.

like image 161
RP Niemeyer Avatar answered Oct 14 '22 21:10

RP Niemeyer