how to build an object like another object?

Viewed 120

There are some inputs. I have generated an object from the value of those inputs. So, my generated object is something like this:

var generate_fields = {
  name: "Mike",
  email: "mike@gmail.com",
  gender: "1",
  hobby: ["travel", "movie"]
}

And there is a reference object:

var ref_obj = {
    personal_information: {
      name: null,
      password: null,
      gender: null
  },
  business_information: {
    email: null,
    id: null,
  },
  special_information: {
    hobby: null,
    achievement: null
  }
}

I need to create a new object using an object, generate_fields like reference object, ref_obj. So, the new object will be:

var custom_obj = {
    personal_information: {
     name: "Mike",  
     gender: "1",
  },
  business_information: {
    email: "mike@gmail.com",
  },
  special_information: {
    hobby: ["travel", "movie"]
  }
}

How to make custom_obj using generate_fields and ref_obj?

Demo:

var ref_obj = {
 personal_information: {
   name: null,
    password: null,
    gender: null
  },
  business_information: {
   email: null,
    id: null,
  },
  special_information: {
   hobby: null,
    achievement: null
  }
}

//console.log(ref_obj);

$('form').submit(function(event) { 
 event.preventDefault();
  var generated_fields = {};
  $(this).find('input, select').not('input[name=submit]').each(function() {
   generated_fields[this.name] = $(this).val();
  });
  console.log(generated_fields);
});
.form-group {
  margin-bottom: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<form>
  <div class="form-group">
    <laberl>Name: </laberl>
    <input type="text" name="name" id="name" placeholder="Name" />
  </div>
  <div class="form-group">
    <label>Email:</label>
    <input type="text" name="email" id="email" placeholder="Email" />
  </div>
  <div class="form-group">
    <label>Gender:</label>
    <select name="gender" id="gender">
      <option value="1">Male</option>
      <option value="2">Female</option>
      <option value="2">Other</option>
    </select>
  </div>
  <div class="form-group">
    <label>Hobbies:</label>
    <select name="hobby" id="hobby" multiple>
      <option value="books">Reading books</option>
      <option value="travel">Travelling</option>
      <option value="movie">Movie</option>
    </select>
  </div>
  <input type="submit" name="submit" value="submit" />
</form>

3 Answers

I would advise you to use generic solution reduce + forEach. Let me try to describe my approach. First of all you should iterate over generated_fields array to determine root level fields and then you have to iterate over each field and check if original object contains the same property

var a1 = {
  name: "Mike",
  email: "mike@gmail.com",
  gender: "1",
  hobby: ["travel", "movie"]
}

var a2 = {
    personal_information: {
      name: null,
      password: null,
      gender: null
  },
  business_information: {
    email: null,
    id: null,
  },
  special_information: {
    hobby: null,
    achievement: null
  }
}

const arr = Object.keys(a2).reduce((a, key) => {
 Object.keys(a2[key]).forEach(value => {
  if(a1.hasOwnProperty(value)){
   a[key] = a[key] || {};
   a[key][value] = a1[value];
  } 
 });
 return a;
}, {});

console.log(arr);

  1. Here is a simple solution without recursion. Note the switch/case section. You must place the values into each property as you specify. This is best and most readable but only if you know the fields in advance. I do not recommend this for large or dynamic objects, where you would instead use the other .reduce, .forEach answer.

  2. Note, this line I changed: var generated_fields = ref_obj;. You may need to use var generated_fields = {...ref_obj}; to get a copy of the object if you are creating multiple.

  3. Your first <label> is mistyped as <laberl>

var ref_obj = {
 personal_information: { name: null, password: null, gender: null },
  business_information: { email: null, id: null, },
  special_information: { hobby: null, achievement: null }
}

$('form').submit(function(event) { 
 event.preventDefault();
  var generated_fields = ref_obj;
  $(this).find('input, select').not('input[name=submit]').each(function() {
  
    switch (this.name) {
      case 'name':
      case 'password':
      case 'gender':
       generated_fields.personal_information[this.name] = $(this).val(); break;
      case 'email':
      case 'id':
        generated_fields.business_information[this.name] = $(this).val(); break;
      case 'achievement':
      case 'hobby':
       generated_fields.special_information[this.name] = $(this).val(); break;
    }
    
  });
  console.log(generated_fields);
});
.form-group {
  margin-bottom: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<form>
  <div class="form-group">
    <label>Name: </label>
    <input type="text" name="name" id="name" placeholder="Name" />
  </div>
  <div class="form-group">
    <label>Email:</label>
    <input type="text" name="email" id="email" placeholder="Email" />
  </div>
  <div class="form-group">
    <label>Gender:</label>
    <select name="gender" id="gender">
      <option value="1">Male</option>
      <option value="2">Female</option>
      <option value="2">Other</option>
    </select>
  </div>
  <div class="form-group">
    <label>Hobbies:</label>
    <select name="hobby" id="hobby" multiple>
      <option value="books">Reading books</option>
      <option value="travel">Travelling</option>
      <option value="movie">Movie</option>
    </select>
  </div>
  <input type="submit" name="submit" value="submit" />
</form>

Here's my general solution to your question.

Basically I've copied the "empty" item and used a recursive function to inject the values into it.

var generate_fields = {
  name: "Mike", email: "mike@gmail.com",
  gender: "1", hobby: ["travel", "movie"]
};

var ref_obj = {
  personal_information: { name: null, password: null, gender: null },
  business_information: { email: null, id: null},
  special_information:  { hobby: null, achievement: null }
};


// First, create an exact duplicate of ref_obj
var ans = {...ref_obj};

function isObject(obj) {
  return obj != null && obj.constructor.name === "Object";
}

function copyProperty(obj, name, val) {
  for (let property in obj) {
    if (!obj.hasOwnProperty(property)) continue;
    
    if (isObject(obj[property])) {
      // The recursive case
      copyProperty(obj[property], name, val);
    }
    else if (property === name) { // Note that obj[property] isn't an object
      // Inject the property
      obj[property] = val;
    }
  }
  
  return obj;
}

// Iterate the generate_fields object's properties, and copy each of them to 'ans'
for (let property in generate_fields) {
  if (!generate_fields.hasOwnProperty(property)) continue;
  ans = copyProperty(ans, property, generate_fields[property]);
}

console.log(ans);

Related