Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I dynamically get matching inputs fields to add values to an object in Javascript?

I've a page with two input fields. I've a JS object (info) containing 'reference' and a 'value' field of each item. For each item, there's a corresponding 'input' field with matched by 'class' attribute. When a user updates a matching input field, I want to add it's 'value' in the info object.

The problem I'm experiencing is that it's putting the value in the last item in the array (location.value) for either input.

Can anyone help me with where I'm going wrong please? (I could see solutions using 'each' where data for all inputs needs to be added to an array/object. I'm stuck on getting the data for matched fields.)

$(document).ready(function() {
  var info = {
    name: {
      ref: "a2350",
      value: ""
    },
    location: {
      ref: "a2351",
      value: ""
    }
  };
  for (var p in info) {
    if (info.hasOwnProperty(p)) {
      $('input.' + p).focusout(function() {
        var val = $(this).val();
        info[p].value = val; // Only setting value on the last item in array!
        //console.log(p);   /// p = always location!
        out();
      })
    }
  }

  function out() {
    console.log(info);
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<input type="text" class="name" />
<input type="text" class="location" value="" />
like image 920
Emily Rose Avatar asked Aug 23 '17 14:08

Emily Rose


2 Answers

Your issue is because p will be location when the loop ends. Therefore all the click handlers will update the location object, regardless of which element they are attached to.

To fix this you can use a closure to retain the scope of the p at the point the event handler logic was created. Also note that hasOwnProperty() is moot when you're looping through the properties of the object; it has to exist for the iteration to happen. Try this:

$(document).ready(function() {
  var info = {
    name: {
      ref: "a2350",
      value: ""
    },
    location: {
      ref: "a2351",
      value: ""
    }
  };

  for (var p in info) {
    (function(p) {
      $('input.' + p).focusout(function() {
        var val = $(this).val();
        info[p].value = val;
        out();
      })
    })(p);
  }

  function out() {
    console.log(info);
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

<input type="text" class="name" />
<input type="text" class="location" value="" />

Alternatively, you can avoid the loop and associated closure by using the class on the input to retrieve the required object:

$(document).ready(function() {
  var info = {
    name: {
      ref: "a2350",
      value: ""
    },
    location: {
      ref: "a2351",
      value: ""
    }
  };

  $('input').focusout(function() {
    var className = $(this).attr('class');
    if (info.hasOwnProperty(className))
      info[className].value = this.value;
    out();
  });

  function out() {
    console.log(info);
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

<input type="text" class="name" />
<input type="text" class="location" value="" />
like image 66
Rory McCrossan Avatar answered Sep 22 '22 16:09

Rory McCrossan


You can simply use the class attribute to update the object by key:

$(document).ready(function(){
  var info = {
    name: {
      ref: "a2350",
      value: ""
    },
    location: {
      ref: "a2351",
      value: ""
    }
  };
  
  $('input').focusout(function() {
      var className = $(this).attr('class');
      var inputValue = $(this).val();
      if (info.hasOwnProperty(className)) {
        info[className].value = inputValue;
      } else {
        // If you want to add unknown inputs to the object 
        info[className] = {ref: "", value: inputValue};
      }
          
      console.log(info);
    });
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input type="text" class="name" />
<input type="text" class="location" value="" />
<input type="text" class="not_exists" value="" />
like image 29
aabilio Avatar answered Sep 20 '22 16:09

aabilio