I have a problem with jQuery, I want to pass two parameters in different functions but I don't succeed and get an error on the console:
Invalid or unexpected token
This is my code:
@model UsersWithCoursesViewModel
@{
this.ViewData["Title"] = "Evaluation";
int counter = 1;
}
<h1 >@this.ViewData["Title"]</h1>
<table >
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Username</th>
<th scope="col">Course</th>
<th scope="col">Grade</th>
</tr>
</thead>
<tbody>
@foreach (var course in Model.Courses)
{
<tr>
<th>@counter</th>
<td>@course.AddedByUser</td>
<td>@course.CourseName</td>
<td id="evaluation">
@course.Grade
<a onclick="addInput(@course.CourseId, '@course.AddedByUserId')">Change</a>
</td>
</tr>
counter ;
}
</tbody>
</table>
@section Scripts {
<script>
function addInput(courseId, addedByUserId) {
$("#evaluation").remove(".a").text(null).prepend("<label for='evaluation_input'>Evaluate</label><input id='evaluation_input' type='number' /><a class='btn btn-warning' onclick='evaluates(" courseId ", " addedByUserId ")'>Save</a>")
}
function evaluates(courseId, addedByUserId) {
const evaluation = $("#evaluation_input").val();
console.log(userId)
}
</script>
}
When I click on the button with event addClick()
, everything is OK (the input appears and courseId
and addedByUserId
are written in the console), but when I click the button with the name Save and "evaluates" function, I get that error "Invalid or unexpected token". I think the problem is coming from addedByUserId
variable, it is GUID, and when I change this
onclick='evaluates(" courseId ", " addedByUserId ")
to this
"evaluates(" courseId ", " 5 ")"
there is no problem (the console outputs "5").
CodePudding user response:
The main issue is due to fact that you need to wrap the parameter values of the inline event handler in quotes. These quotes themselves need to be escaped as well so that they don't interfere with both the JS string you're building and also the syntax of the HTML attribute you're building. The correct syntax would be this:
function addInput(courseId, addedByUserId) {
$("#evaluation").remove(".a").text(null).prepend('<label for="evaluation_input">Evaluate</label><input id="evaluation_input" type="number" /><a onclick="evaluates(\'' courseId '\', \'' addedByUserId '\')">Save</a>');
}
function evaluates(courseId, addedByUserId) {
const evaluation = $("#evaluation_input").val();
console.log(evaluation)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table >
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Username</th>
<th scope="col">Course</th>
<th scope="col">Grade</th>
</tr>
</thead>
<tbody>
<tr>
<th>1</th>
<td>AddedByUser_1</td>
<td>CourseName_1</td>
<td id="evaluation">
Grade_1
<a onclick="addInput(1, 'AddedByUserId_1')">Change</a>
</td>
</tr>
<tr>
<th>2</th>
<td>AddedByUser_2</td>
<td>CourseName_2</td>
<td id="evaluation">
Grade_2
<a onclick="addInput(2, 'AddedByUserId_2')">Change</a>
</td>
</tr>
<tr>
<th>3</th>
<td>AddedByUser_3</td>
<td>CourseName_3</td>
<td id="evaluation">
Grade_3
<a onclick="addInput(3, 'AddedByUserId_3')">Change</a>
</td>
</tr>
</tbody>
</table>
- Update -
However this is rather ugly code, due to the building of the inline event handler at runtime, and also has a bug whereby no matter which 'Change' link you click the edit input
is only added to the first row.
To fix the first problem use unobtrusive event handlers with data
attributes to hold the element metadata. To fix the second problem use common classes on all the repeated HTML structures along with DOM traversal methods to target them based on the a
element which was clicked.
The corrected code would look like this:
jQuery($ => {
let $template = $('#evaluation-template');
$('.btn.change').on('click', e => {
let $btn = $(e.target);
let template = $template.html().replace('[courseid]', $btn.data('courseid')).replace('[addedbyuserid]', $btn.data('addedbyuserid')).trim();
$btn.closest('.evaluation').html(template);
});
$(document).on('click', '.btn.save', e => {
let $btn = $(e.target);
console.log($btn.data('courseid'), $btn.data('addedbyuserid'));
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table >
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Username</th>
<th scope="col">Course</th>
<th scope="col">Grade</th>
</tr>
</thead>
<tbody>
<tr>
<th>1</th>
<td>AddedByUser_1</td>
<td>CourseName_1</td>
<td >
Grade_1
<a data-courseid="1" data-addedbyuserid="AddedByUserId_1">Change</a>
</td>
</tr>
<tr>
<th>2</th>
<td>AddedByUser_2</td>
<td>CourseName_2</td>
<td >
Grade_2
<a data-courseid="1" data-addedbyuserid="AddedByUserId_2">Change</a>
</td>
</tr>
<tr>
<th>3</th>
<td>AddedByUser_3</td>
<td>CourseName_3</td>
<td >
Grade_3
<a data-courseid="1" data-addedbyuserid="AddedByUserId_3">Change</a>
</td>
</tr>
</tbody>
</table>
<script type="text/template" id="evaluation-template">
<label for="evaluation_input">Evaluate</label>
<input type="number" />
<a data-courseid="[courseid]" data-addedbyuserid="[addedbyuserid]">Save</a>
</script>