Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Invalid or unexpected token in JQuery with Blazor and ASP Net Core

I have a problem with jQuery, I want to pass two parameters in different functions but I don’t succeed console writes me "Invalid or unexpected token". This is my code.

@model UsersWithCoursesViewModel

@{
this.ViewData["Title"] = "Evaluation";
int counter = 1;
}

<h1 class="text-center mt-3 mb-3">@this.ViewData["Title"]</h1>

<table class="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 class="d-flex justify-content-between" id="evaluation">
                @course.Grade
                <a class="btn btn-warning" 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 writes me "Invalid or unexpected token". I think the problem is coming from addedByUserId variable, she is GUID, and when I change this
onclick='evaluates(" + courseId + ", " + addedByUserId + ")
into this "evaluates(" + courseId + ", " + 5 + ")" not a problem(the console writes me "5").

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

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 class="btn btn-warning" 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 class="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 class="d-flex justify-content-between" id="evaluation">
        Grade_1
        <a class="btn btn-warning" onclick="addInput(1, 'AddedByUserId_1')">Change</a>
      </td>
    </tr>
    <tr>
      <th>2</th>
      <td>AddedByUser_2</td>
      <td>CourseName_2</td>
      <td class="d-flex justify-content-between" id="evaluation">
        Grade_2
        <a class="btn btn-warning" onclick="addInput(2, 'AddedByUserId_2')">Change</a>
      </td>
    </tr>
    <tr>
      <th>3</th>
      <td>AddedByUser_3</td>
      <td>CourseName_3</td>
      <td class="d-flex justify-content-between" id="evaluation">
        Grade_3
        <a class="btn btn-warning" 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 class="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 class="d-flex justify-content-between evaluation">
        Grade_1
        <a class="btn btn-warning change" data-courseid="1" data-addedbyuserid="AddedByUserId_1">Change</a>
      </td>
    </tr>
    <tr>
      <th>2</th>
      <td>AddedByUser_2</td>
      <td>CourseName_2</td>
      <td class="d-flex justify-content-between evaluation">
        Grade_2
        <a class="btn btn-warning change" data-courseid="1" data-addedbyuserid="AddedByUserId_2">Change</a>
      </td>
    </tr>
    <tr>
      <th>3</th>
      <td>AddedByUser_3</td>
      <td>CourseName_3</td>
      <td class="d-flex justify-content-between evaluation">
        Grade_3
        <a class="btn btn-warning change" 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 class="evaluation_input" type="number" />
  <a class="btn btn-warning save" data-courseid="[courseid]" data-addedbyuserid="[addedbyuserid]">Save</a>
</script>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading