Say I have the following simplified HTML form:
<form class = 'crud'>
<div class = 'record' id='record_0'>
<input id='testa_0' name='testa' class = 'crud-control'>
<input id='testb_0' name='testb' class = 'crud-control'>
</div>
<div class = 'record' id='record_1'>
<input id='testa_1' name='testa' class = 'crud-control'>
<input id='testb_1' name='testb' class = 'crud-control'>
</div>
<div class = 'record' id='record_2'>
<input id='testa_2' name='testa' class = 'crud-control'>
<input id='testb_2' name='testb' class = 'crud-control'>
</div>
</form>
Within the data-update
attribute of the div.record
elements, I'm storing the values modified/entered by the user in the input fields in an object {testa: newvalue, testb: othervalue}
(until they are submitted to a database -- I'm skipping that submission step here for less code/complexity). I'm updating the data-update attribute using a jquery event handler:
$( 'form.crud, table.crud' ).each(function(i,crud) {
$(crud).find('.crud-control').change(function() {
let $record = $($(this).closest( '.record' ));
$record.data('update',{...$record.data('update'),...{[$(this).attr( 'name' )]:$(this).val()}});
});
});
This code works, but the $record.data('update', ...
looks a little too complicated to be the best solution. Is there a better method to extend a data-xxx stored object with a key/value pair?
I tried:
$.extend( $record.data('update'), {[$(this).attr( 'name' )]:$(this).val()})
But this - for some reason, which I fail to understand - updates the data-update
attribute for all div.record
s and not only the one closest()
to the input.crud-control
updated.
Any ideas?
You were very close. If you want to create a new object, it's basically a combination of the two:
$record.data(
'update',
// Create a new object
{
// Spread out the previous object's properties into it (if any)
...$record.data('update'),
// Add the new property using computed property name syntax
[$(this).attr( 'name' )]: $(this).val()
}
);
But note that there's no reason for $(this).attr('name')
, just use this.name
, it's entirely standard. Similarly, $(this).val()
is unnecessary with input
elements, just this.value
is sufficient.
With those applied:
$record.data(
'update',
// Create a new object
{
// Spread out the previous object's properties into it (if any)
...$record.data('update'),
// Add the new property using computed property name syntax
[this.name]: this.value
}
);
Alternatively, you can update the existing object if present (since you're using jQuery's data
method, it remains an object, it's not making a round-trip through text):
const object = $record.data("update") || {};
object[this.name] = this.value;
$record.data("update", object);
If you data-update="{}"
to the HTML markup for the elements so you know the object will be there, then you can just do:
$record.data("update")[this.name] = this.value;
Again, since this is using jQuery's data
(only getting initial values from the data-update
attribute), the object is stored as an object, not text.