Skip to main content
  1. About
  2. For Teams
Asked
Viewed 7k times
4

I'm trying to create a JavaScript function that creates an object using strings for structure and fills it from DOM data.

For example, the following strings could look like this:

some.example.here = "hello"
some.example.there = "hi"
other.example = "heyo"

Which should create this object:

{
    some: {
        example: {
            here: "hello",
            there: "hi"
        },
    other: {
        example: "heyo
    }
}

The data as said comes from DOM and is being load at the code segment labeled "read data into object". The data loads fine and the object structure is being setup fine as well, but the data is not being put into the data field.

Here's the code for the function:

function getDataFromElement(element) {
  obj = {};
  $(element)
    .find("[data-value]")
    .each(function() {
      // create object node
      valueObj = {};
      currentValueObj = valueObj;
      $.each($(this).attr("data-value").split("."), function(i, objpath) {
        currentValueObj[objpath] = {};
        currentValueObj = currentValueObj[objpath];
      });

      // read data into object
      if($(this).is("[data-putvalue]") && $(this).attr("data-putvalue") != "html") {
        currentValueObj = $(this).attr($(this).attr("data-putvalue"));
      } else {
        currentValueObj = $(this).html();
      }

      console.log(currentValueObj);

      // combine with previous gathered data
      obj = $.extend(true, {}, obj, valueObj);
    });

  return obj;
}

Does anyone know what to do?

4
  • Can include html at Question? , create stacksnippets , jsfiddle jsfiddle.net to demonstrate ?
    guest271314
    –  guest271314
    2015-08-15 21:32:51 +00:00
    Commented Aug 15, 2015 at 21:32
  • What is purpose of currentValueObj = currentValueObj[objpath]; ?
    guest271314
    –  guest271314
    2015-08-15 21:38:57 +00:00
    Commented Aug 15, 2015 at 21:38
  • With the second each loop I'm trying to create the object structure, so the loop goes through each element of the string, creates a new subelement with the current string-element-name with currentValueObj[objpath] = {}; and goes into that subelement with currentValueObj = currentValueObj[objpath];, so that in the next loop-walk the next subelement will be created there.
    Lukas Bach
    –  Lukas Bach
    2015-08-15 21:46:56 +00:00
    Commented Aug 15, 2015 at 21:46
  • currentValueObj appear overwritten at each iteration ? Can include html at Question , create stacksnippets to demonstrate ?
    guest271314
    –  guest271314
    2015-08-15 21:51:05 +00:00
    Commented Aug 15, 2015 at 21:51

4 Answers 4

4

I would do it like this:

var createObject = function(model, name, value) {
  var nameParts = name.split("."),
  currentObject = model;
  for (var i in nameParts) {
    var part = nameParts[i];
    if (i == nameParts.length-1) {
      currentObject[part] = value;
      break;
    }
    if (typeof currentObject[part] == "undefined") {
      currentObject[part] = {};
    }
    currentObject = currentObject[part];
  }
};

And then use it like that:

var model = {};
createObject(model, "some.example.here", "hello");
createObject(model, "some.example.there", "hi");
createObject(model, "other.example", "heyo");
Sign up to request clarification or add additional context in comments.

1 Comment

this creates different models/objects for each key-value
3

Some functional implementation:

const value = 'hello';
'some.example.here'.split('.').reverse().reduce((reduction, segment, index) => {
  const result = {};
  if (index === 0) {                                                                 
    result[segment] = value;
  } else {                                                               
    result[segment] = reduction;
  }

  return result;
}, {})

1 Comment

where does that currentTarget comes from?
2

Probably this can suit you (adapted from another project of mine, adapt and use as needed): NOTE the element's name is taken as key and value as the value

function fields2model( $elements, dataModel )
{
    $elements.each(function( ){
        var $el = $(this), 
            name = $el.attr('name'), 
            key, k, i, o, val
        ;

        key = name;

        val = $el.val() || '';

        k = key.split('.'); o = dataModel;
        while ( k.length )
        {
            i = k.shift( );
            if ( k.length ) 
            {
                if ( !o.hasOwnProperty( i ) ) o[ i ] = /^\d+$/.test( k[0] ) ? [ ] : { };
                o = o[ i ];
            }
            else 
            {
                o[ i ] = val;
            }
        }
    });
}

Example use:

<input name="some.example.here" value="hello" />
<input name="some.example.there" value="hi" />


var model = {};
fields2model($('input,textarea,select'), model);

The example elements above will give the below model:

model = {
some: {
    example: {
        here: "hello",
        there: "hi"
    }
};

2 Comments

I tried your function here: plnkr.co/edit/NhsnQJs1iYWKUCff2aVU?p=preview but it did not work - probably my mistake. Can you help, please?
I got it working: plnkr.co/edit/EyGmop9CmYO3WAf9odvU Javascript is strange - isn't it? ;-)
1

@theFreedomBanana +1

Works for me

const magicFunction = (string, value) =>
  string
    .split('.')
    .reverse()
    .reduce((acc, cur, index) => ({ [cur]: index === 0 ? value : acc }), {});

1 Comment

Please don't add "thank you" as an answer. Instead, just vote up the answers that you find helpful. - From Review

Your Answer

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.

Morty Proxy This is a proxified and sanitized view of the page, visit original site.