skip to Main Content

This code works properly:

$(document).ready(function () {
    $.getJSON('./record.json', function (data) {
        var studentsHTML = '<ul>';
        $.each(data, function (index, student) {
            studentsHTML +='<li>' + student.name + '</li>';
        });
        studentsHTML += '</ul>';
        $('#students').html(studentsHTML);
    });
}); 

But this doesn’t:

$(document).ready(function () {
    $.getJSON('./record.json', function (data) {
        var studentsHTML = '<ul>';
        $.each(data, function (index, student) {
            studentsHTML +='<li onclick="showSubject(' + student.subject + ')">' + student.name + '</li>';
        });
        studentsHTML += '</ul>';
        $('#students').html(studentsHTML);
    });
    function showSubject(subj) {
        alert(subj);
    }
}); 

It gives the error message:
"ReferenceError: showSubject is not defined"

A simple alert() function works, but only with the ‘index’ parameter:

onclick="alert(' + index + ')"

It shows the indexes of the items properly. But nothing else. Eg.: alert does not work with "student.subject" too.

Is there a way to make my list elements clickable?

3

Answers


  1. The issue stated is

    showSubject is not defined

    so the onclick= is not able to find your function.

    When you use onclick= with a function, that function must be defined as a global. Defining it within the doc.ready block makes it only available within that doc.ready block, it’s not global, so onclick can’t find it

    Move the function outside of doc.ready and it will find it.

    There is also an error with missing quotes, around the argument, added in the snippet below.

    $(document).ready(function () {
        var data = [ 
          { subject: "Subject1", name: "Name1" },
          { subject: "Subject2", name: "Name2" },
          { subject: "Subject3", name: "Name3" }
        ];
        
        //$.getJSON('./record.json', function (data) {
            var studentsHTML = '<ul>';
            $.each(data, function (index, student) {
                studentsHTML +='<li onclick="showSubject('' + student.subject + '')">' + student.name + '</li>';
            });
            studentsHTML += '</ul>';
            $('#students').html(studentsHTML);
        //});
    }); 
    
    function showSubject(subj) {
        alert(subj);
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div id="students"></div>

    As a bonus, the recommend way to do this is with event delegation:

    $(document).ready(function () {
    
        // added here to confirm it's using delegation
        $(document).on("click", "#students > ul > li", function() {
            showSubject($(this).data("subject"));
        });
     
        var data = [ 
          { subject: "Subject1", name: "Name1" },
          { subject: "Subject2", name: "Name2" },
          { subject: "Subject3", name: "Name3" }
        ];
        
        //$.getJSON('./record.json', function (data) {
            var studentsHTML = '<ul>';
            $.each(data, function (index, student) {
                studentsHTML +='<li data-subject="' + student.subject + '">' + student.name + '</li>';
            });
            studentsHTML += '</ul>';
            $('#students').html(studentsHTML);
        //});
    
        // this is now called from the delegated event handler within doc.ready, 
        // so can be defined in doc.ready instead of globally
        function showSubject(subj) {
            alert(subj);
        }
    }); 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div id="students"></div>
    Login or Signup to reply.
  2. Problem you have is the scope of the function and not quoting the value inside the function call. It is better to not use inline events, but to bind event listeners to the element.

    You would be better off using event delegation and data attributes

    $(document).ready(function() {
      // bind click handler to students, listen for clicks on li elements
      // event delegation
      $("#students").on("click", "li", function() {
        // get the li that was clicked
        var li = $(this);
        // read the data attribute
        var subject = li.data("subject");
        console.log(subject);
      });
    
      $.getJSON('./record.json', function(data) {
        var studentsHTML = '<ul>';
        $.each(data, function(index, student) {
          studentsHTML += '<li data-subject="' + student.subject + '">' + student.name + '</li>';
        });
        studentsHTML += '</ul>';
        $('#students').html(studentsHTML);
      });
    
    });
    
    Login or Signup to reply.
  3. inspect the li element on which you have added the onclick event.
    Your onclick look like this:-
    showSubject(‘Math’)

    Not like this:-
    showSubject(Math)

    the fix would be properly escape the quotes as shown by freedomn-m

    and it should work

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search