Encountered a problem when trying to add an onclick event to dynamically created HTML: Uncaught SyntaxError: Unexpected identifier was

Utilizing ajax to fetch results from the code behind, I am dynamically creating divs upon receiving those results. The process works smoothly without any issues.

Now, my objective is to attach an onclick event to each div that triggers a specific method when clicked. Here is my complete code:

<script>
    function onSelectGroup(Id) {
        $.ajax({
            method: "GET",
            url: "Product/GetProductsByGroupId",
            data: { groupId: Id }
        })
.done(function (response) {

    $(".products").html("");
    for (var i = 0; i < response.length; i++) {
//I wrote onclick = "addProduct(response[i])" to generate for each div each onclick event
        let item = '<div class="col-md-3"> <div class="Product-holder" onclick="addProduct(' + response[i] + ')" id=' + response[i].ProductId + '><img class="img-responsive" src="images/maxresdefault.jpg"><p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p></div></div>';
        //Trying to append it to my .product class because it's parent of this divs above
        $(".products").append(item);

    }})};

    function addProduct(product) {
        console.log(product.Title);
    }
</script>

However, encountering an error stating "Uncaught SyntaxError: Unexpected identifier" when clicking on any of the generated divs:

Uncaught SyntaxError: Unexpected identifier

I have been trying to resolve this issue for the past 3 hours and seem to be stuck at this point.

Your assistance in troubleshooting would be highly appreciated. Thank you.

P.S

CODE BEHIND - C # METHOD:

public ActionResult GetProductsByGroupId(int groupId)
{
            var products = ProductController.GetProductsByGroupId(groupId);
            if(products)
            {
                List<Product> productlist = new List<Product>();
                foreach (var item in products)
                {
                    Product product = new Product();
                    product.ProductId = Convert.ToInt32(item.Id);
                    product.Price = Convert.ToDecimal(item.Price);
                    product.Title = item.Title;
                    productlist.Add(product);
                }

                return Json(productlist, JsonRequestBehavior.AllowGet);
            }

            return Json(products, JsonRequestBehavior.AllowGet);
}

Answer №1

To enhance user experience, it is recommended to eliminate the onclick attribute and opt for using delegate instead. By passing an object to a function that converts response[i] into text as [Object object], one can utilize data-* attributes to store data for each object. Subsequently, attaching an event to the div holding the class product allows for the utilization of $(this) to target the currently selected div and access its data attributes.

$(".products").html("");
 var response = [{ProductId:4, Title:"Doe", Price: 34.89}, {ProductId:6, Title:"Jane", Price: 20.99}];
    for (var i = 0; i < response.length; i++) {
//I wrote onclick = "addProduct(response[i])" to generate for each div each onclick event
        let item = '<div class="col-md-3"> <div class="Product-holder product" data-price="'+ response[i].Price +'" data-title="' + response[i].Title + '" id=' + response[i].ProductId + '><img class="img-responsive" src="images/maxresdefault.jpg"><p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p></div></div>';
        //Trying to append it to my .product class because it's parent of this divs above
        $(".products").append(item);
//console.log(item);
    };
    
$(document).on('click', '.product', function(){
  var product = {Title: $(this).data('title'), ProductId: $(this).attr('id'), Price: $(this).data('price')};
  console.log(product);
  // here use ajax to add this product
});
body {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="products"></div>

Answer №2

Check out this amazing method called Delegate in jQuery!

Overview: Delegate allows you to attach a handler to one or more events for all elements that match the selector, both now and in the future, based on specific root elements.

The key here is to bind the onClick event to the parent div and specify a selector that will target child divs added later.

<script>
function onSelectGroup(Id) {
    $.ajax(
        //Make your ajax call here
    ).done(function (response) {
    for (var i = 0; i < response.length; i++) {
        let item = '<div class="event-target"></div>'
        $(".products").append(item);
}})};

// This is where the magic happens.
// We assign the event to elements with the 'event-target' class
// inside the element with the 'products' class.

$('.products').on('click', '.event-target', function(){
    console.log(this);
})
</script>

Caution: Be cautious when using delegate as choosing the wrong selector can result in triggering the event for every element on the page or even recursively (trust me, I've been there...)

Answer №3

Utilize data attributes to store information and retrieve it on click events. Note that the code has not been tested but is expected to function properly.

let item = '<div class="col-md-3">' +
    ' <div class="Product-holder" ' +
    'onclick="addProduct(this)"' +
    ' data-title="'+response[i].Title+'"' +
    ' id=' + response[i].ProductId + '>' +
    '<img class="img-responsive" src="images/maxresdefault.jpg">' +
    '<p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p>' +
    '</div>' +
    '</div>';
$(".products").append(item);

function addProduct(product) {
    console.log($(product).data('title'));
}

It is important to delegate the event for dynamically created elements.

$("body").on("click",".Product-holder",function(){
   console.log($(product).data('title'));
})

In this scenario, the inline event handler using `onclick` will become unnecessary.

Answer №4

Allow me to elucidate your code.

 for (var i = 0; i < response.length; i++) {
        let item = '<div class="col-md-3"> <div class="Product-holder" onclick="addProduct(' + response[i] + ')" id=' + response[i].ProductId + '><img class="img-responsive" src="images/maxresdefault.jpg"><p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p></div></div>';
        $(".products").append(item);
    }})};

Upon reviewing this snippet of code, I noticed that you are concatenating strings to a variable. The issue arises with response[i].ProductId as it appears that response[i] is an object. In JavaScript, you cannot directly add an object to a string using the + operator, which will result in "string [object] string". How can we resolve this??

  1. One solution is to convert your object to a JSON String such as {"id": 123, "name": "Product name"}, which will be displayed in the HTML code like this: onclick='addProduct({"id": 123, "name": "Product name"})'. Please note that the onclick attribute should use ' instead of ".

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Sending Data from Model to Controller with Ajax in ASP.NET 5 / MVC 6

I'm encountering a problem in my ASP.NET 5 MVC 6 application when trying to use Ajax to post data to my controller. I have successfully done this in ASP.NET MVC 5, and even tested the exact same code in a new ASP.NET MVC 5 project where it worked perf ...

Sending back an Observable from a rejected Promise

I am currently investigating whether I can convert a Promise rejection into a typed Observable. Within my login component, I have a function that looks like this... login() { const login$ = this.authenticationService.login(this.loginForm.value) login$ ...

Discovering React Flowtype's Node.contains() event target

In my React code, I have set up an event listener like this: document.removeEventListener("mouseup", this.handleDocumentClick); I found the definition of the method in Flow's source code, and it looks like this: removeEventListener(type: MouseEvent ...

Ensuring the confirmation password is validated using Vue/Quasar

As a beginner in Vue, I'm writing code to connect to an application using Vue/Quasar/C#. However, I am struggling to understand how rules are executed. The specific code snippet I have written is aimed at checking if the input fields for passwords are ...

Exploring AngularJS: Retrieving data based on a specific ID from a JSON document

Within my controller class, I extract the ID of a specific user from the URL and pass it on to the OrderService. My goal now is to fetch the data associated with this ID from a JSON file. How can I accomplish this task? OrderCtrl 'use strict'; ...

Having trouble retrieving data in a foreach loop within CodeIgniter

I have written some HTML code for a simple query in CodeIgniter, but as a beginner, I am unsure of what mistakes I may have made. The code is supposed to retrieve records from a table. Can anyone please help me troubleshoot? <?php foreach($records as $ ...

The CSS background fails to expand to the entire height of the element

I'm encountering an issue where an element with 100% height is extending beyond its boundaries when there are multiple blocks. For a demonstration, you can refer to this jsfiddle example: http://jsfiddle.net/yPqKa/ Any suggestions on how to resolve ...

The map displayed on google.com appears different from the one featured on our website

The integration of the JS for the Google map on our website is working smoothly without any issues. However, when I zoom into our address on google.com/maps, our Hotel is listed as "Hotel". On the map displayed on our website, there are only a few entries ...

Ways to extract the ID by iterating through buttons

I encountered a message in my browser while looping through buttons with onclick function(). Are there any alternative solutions? Error handling response: TypeError: self.processResponse is not a function at chrome-extension://cmkdbmfndkfgebldhnkbfhlneefd ...

When the async attribute is added to the HTML code, Angular is no longer defined

Looking to optimize the performance of my website in Chrome Audit, I decided to add 'async' to my script tag like this: <body ng-cloak id="body"> <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry ...

Adapting my JavaScript code to handle one-dimensional CSV data instead of the usual two-dimensional format

How can I effectively parse this CSV file using JavaScript? 1363085391,42.890000000000,5.432200000000 1363088879,47.570000000000,4.981800000000 1363120475,56.560000000000,1.768000000000 1363132522,53.000000000000,1.000000000000 1363214378,48.630000000000, ...

Error: Material UI encountered a problem with type error - number 0 cannot be iterated (property Symbol(Symbol.iterator) cannot be read)

I am currently working with the MUI(Material UI) App bar. You can find it here. The version I am using is v6.1.1. In the sandbox environment, everything seems to work fine when testing. However, when implementing it into my project, I encounter the follo ...

Enhancing Option Element Height with Padding in Bootstrap 5

Is there a way to adjust the height or increase padding of the option element within a standard select box using Bootstrap 5? More information can be found at: https://getbootstrap.com/docs/5.0/forms/select/ Could you provide an example code to demonstrat ...

Tips for customizing the default configuration files in reactJs bootstrapping using npm

I've generated a simple greeting world ReactJS application by using the create-react-app command from npm. The directory structure provided by the application template is as follows: https://i.sstatic.net/y3K5n.png The contents of my package.json fi ...

"Changing the title using a button or anchor: A step-by-step guide

Is there a way to update the title each time a button is clicked on my one-page site that directs to different anchors at the top? ...

Refresh in AJAX, automated loading for seamless transition to a different page

Having an issue with the page not auto-refreshing, although it loads when I manually refresh. P.S Loading the page onto another page. Below is my HTML and AJAX code along with its database: The Trigger Button <?php $data = mysqli_query ...

Ways to prevent negative values from appearing in the text field

Check out this code snippet on Fiddle. I need help with a text field that should only display positive values. If the input is negative, I want it to be stored in ng-model but not shown in the textbox. function LoginController($scope) { $scope.number = ...

PHP successfully redirects data with Ajax

Encountering another issue here. While I believe it's not a complex problem to tackle, my exposure to Ajax is limited. The dilemma at hand involves redirecting upon successful completion. To provide a clearer idea, I am sharing the if statements snip ...

What is the best way to retrieve "text" from a function using JavaScript with Selenium web driver?

Update: The solution provided by Jonas has successfully resolved most of the issues. Currently, I am exploring options to utilize datepicker or sendkeys to set the date range as it continues to increment by one day each time the code is rerun. date_start = ...

Coldfusion has the ability to automatically save data without the need

Is it possible to save data to a database in Coldfusion without the traditional form posting and save button? What about saving information as the user exits the field - is this considered good practice? ...