VicYork VicYork - 5 months ago 9
Javascript Question

Dynamically scaffold a JavaScript Object based on a string path

I'm attempting to dynamically build a JavaScript object from a string path recursively. The end goal is to have an object that is dynamically generated on some event.

Here's what I have so far, but I can't figure out why it's not working:
jsfiddle link: https://jsfiddle.net/1Lo7uart/

HTML

<input type="text" data-path="/foo/bar/ni">
<input type="text" data-path="/foo/bar/ni">
<input type="text" data-path="/foo/bar/san">
...


JavaScript

var storage = {};
var fields = $('.fields');

fields.find('input').each(function() {
var field = $(this);
field.change(function(event) {
var currentField = $(this),
currentFieldPath = currentField.attr('data-path').split('/').slice(1),
currentFieldValue = currentField.val();

function bindData(path, val, store) {
if (store) {
if (store.hasOwnProperty(path[0])) {
if (path.length === 1) {
store[path[0]] = val;
} else {
path.shift();
bindData(path, val, store[path[0]]);
}
} else {
if (path.length === 1) {
store[path[0]] = val;
} else {
store[path[0]] = {};
var annex = path.shift();
bindData(path, val, store[annex]);
}
}
}
}

bindData(currentFieldPath, currentFieldValue, storage);

});
});
...


Ideally, this should result in something like;

{
foo: {
bar: {
ni: 'some value, that'
s been over written by the second input ',
san: 'some value here'
}
...
}
}


The recursion works the first time around, but not ever after, haha. Any thoughts?

Answer

You were using the wrong object path (store[path[0]) in your code (line 18 of the jsfiddle.

Use this:

} else {
        var ann = path.shift();
        //console.log('path', store, path[0], ann, //store[path[0]], store[ann][path[0]])
        console.log('path', path, val)
        bindData(path, val, store[[ann]]);
}

instead of :

} else {
    path.shift();
    bindData(path, val, store[path[0]]);
}

Your path is an array of ['foo', 'bar', 'blablah'], so shifting removes 'foo' from the array. But you are trying to store your inputs at store['foo']['bar'], so doing store[path[0]] is trying to access an object at store['bar'] which doesn't exist.

Here is a working version

https://jsfiddle.net/j87m4z71/