Suppose, I don’t know for sure if there are checked authorities
or not (but if they are present, I want them). If checked authorities
are absent, I want jQuery to select authorities
with no regard whether they are checked or not (in practice, it would mean retrieving the value of a hidden input). My idea of using JS’s "truthy"/"falsy" concept for handling this kind of situations was this:
let user = {
id: $(this).find('[name=id]').val(),
username: $(this).find('[name=username]').val(),
password: $(this).find('[name=password]').val(),
name: $(this).find('[name=name]').val(),
lastName: $(this).find('[name=lastName]').val(),
department: $(this).find('[name=department]').val(),
salary: $(this).find('[name=salary]').val(),
age: $(this).find('[name=age]').val(),
email: $(this).find('[name=email]').val(),
enabledByte: $(this).find('[name=enabledByte]').val(),
authorities: JSON.parse($(this).find('[name=authorities]:checked').val()) ||
JSON.parse($(this).find('[name=authorities]').val())
};
However, it doesn’t work. Funnily enough, it does work in the code snippet below. Isn’t undefined
, returned by val()
in case of a failed match, falsy? Go figure! My best guess is that JSON.parse()
throws an error when parsing an undefined
instead of returning some falsy value, as I want it to. The method doesn’t accept "param OR param", does it?
How do you think I should provide that kind of fallbacks in my case (other than, of course, checking the falsiness of checked authorities
separately which would be a bit too verbose for my liking)?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>Admin Page</title>
</head>
<body>
<div class="container">
<div class="row mb-2">
<ul class="nav nav-tabs">
<li class="nav-item">
<a class="nav-link active" data-toggle="tab" href="#users-table">All Users</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#add-new-user">Add New User</a>
</li>
</ul>
</div>
<div class="row tab-content">
<div id="users-table" class="tab-pane container active">
<table class="table table-hover text-center">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Last name</th>
<th scope="col">Department</th>
<th scope="col">Email</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>Doe</td>
<td>IT</td>
<td>[email protected]</td>
</tr>
<tr>
<td>Jane</td>
<td>Doe</td>
<td>HR</td>
<td>[email protected]</td>
</tr>
</tbody>
</table>
</div>
<div id="add-new-user" class="tab-pane container">
<h3>Fill in the forms</h3>
<form>
<div class="form-group">
<label for="name">Name: </label>
<input id="name" name="name" type="text" class="form-control" required />
</div>
<div class="form-group">
<label for="last-name">Last name: </label>
<input id="last-name" name="last-name" type="text" class="form-control" required />
</div>
<div class="form-group">
<label for="department">Department: </label>
<select id="department" name="department" class="form-control">
<option value="IT">IT</option>
<option value="HR">HR</option>
<option value="accounting">Accounting</option>
</select>
</div>
<div class="form-group">
<label for="email">Email: </label>
<input id="email" name="email" type="email" class="form-control" />
</div>
<input type="submit" class="btn btn-primary d-flex ml-auto" value="Submit" />
</form>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script>
$(document).ready(function () {
$('form').on('submit', async function (event) {
event.preventDefault();
$('tbody').append(
`<tr>
<td>
${$(this).find('[name=name]').val()}
</td>
<td>
${$(this).find('[name=last-name]').val()}
</td>
<td>
${$(this).find('[name=department]').val()}
</td>
<td>
${$(this).find('[name=email]').val() || 'N/A'}
</td>
</tr>`
);
const submitButton = $(this).find('[type=submit]');
const form = $(this);
submitButton.removeClass('btn-primary')
.addClass('btn-success')
.attr('value', 'User added!')
.attr('type', 'button')
.click(() => $('[href="#users-table"]').tab('show'));
setTimeout(function () {
submitButton.removeClass('btn-success')
.addClass('btn-primary')
.attr('value', 'Submit')
.attr('type', 'submit')
.off('click');
form.trigger('reset');
}, 8000);
});
});
</script>
</body>
</html>
2
Answers
You have a few options depending on your use case:
JSON.parse
s like this. This will make it fall back to the other string before it parses, so it won’t error if the first value isundefined
. However, if both values areundefined
or one is invalid JSON, this will error.undefined
, you can fall back tonull
.null
is a valid JSON value and can be parsed. However, this will still error if either value is invalid JSON.The problem is that
.val()
returnsundefined
if the selector doesn’t find any matches, andJSON.parse(undefined)
raises an exception.Do the fallback inside the argument list of
JSON.parse()
, so you’ll parse whichever value you fetch successfully.