Preventing users from manipulating my form
Tags: javascript, webdev, html
Published: 2022-09-19 06:12:25

Forms are HTML tags that we use in a variety of ways to send the data they hold from one place to another, and then possibly store them somewhere like a database.

---


### Do you know how many different forms we have?
 
In my opinion we have got two different type of forms. 

1. The usual ones like login or register  

2. Some forms (I call the mysterious ones 😜) like `add to cart` or instant logout with a button or even `edit` and `delete` buttons in a list of items.

For the first type, using AJAX doesn't really matter but for the second one, it's essential; because we expect instant response from the website not reloading again and again every time we send a request.

We some times need to send some sensitive data like user ID or the ID of a product ...etc, this happens mostly in the second type of forms, so my main focus in this post is on this type.

Imagine we have a list of products that we've already added it to our cart.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qw8e7rhqffhq4pw5s0jw.png)

As you see there is a tiny multiplication sign next to each item (delete) and a quantity button which should change whenever we reduce or increase the number (update).

To implement these options (delete & update) we need to know which option is being deleted or updated; in other words, we should recognize them.  
 How?

Well, there is just one way (as far as I know) that is specifying the ID of each item and send it along with other values to the server.
You can _hash_ this ID or whatever you want. But there must be a value to identify which item you are operating on.

I usually do that using **hidden type inputs**.

```
<input type="hidden" name="product-id" value='1'>
```
And then send it to the server.

```
$('form').submit(function(){
     $.ajax({
       url : url,
       type: 'POST',
       data: $(this).serialize(),
       success: function(){ alert('Success') },
       error: function(){ alert('Error') }
     })
})
```
I used jQuery but you can use either pure JavaScript for AJAX request.

This process continues well and happily, but imagine the user **manipulate** the ID (By inspecting or developer tools in browsers) that we're sending to the server; We may then operate on the wrong item and what if the ID doesn't exist in our database? Then it will cause an error 😁

The solution is that to simply put a condition in your back-end to check if that ID exists, then do the operation.

But my purpose is to prevent users from _**manipulating**_ the sensitive data of a form before submitting the form. 

My idea is to reset all sensitive data before sending to the server, right after the user submits the form. In this case you can always send true data to the server (although you should keep server-side checks for sure.)

In jQuery when we want to reload child elements inside a parent element we should give an `id` to the parent element.

HTML:
```
<section id="parent">  
    <span>Banana</span>
    <span>Apple</span>
    <span>Orange</span>
</section>
```

JS:

```
$('#parent').load(document.URL + ' #parent > *')
```
By that you're resetting child elements without reloading the whole page and the user will never understand that. 


































_Notice you should keep the space before element ID when concating to document.URL_


Now let's bring this idea back to our previous example about user cart.

Imagine you have a div tag called `#cart-item-{index}` like this for each cart item.
(it's not necessary to have `form` tag when using AJAX)

```
<section id="manage-cart">
   <div id="cart-item-1">
        <span class="close" data-product-id="20">&times;</span>
        <div class="product-details">
          ...
        </div>
   </div>
   <div id="cart-item-2">
        <span class="close" data-product-id="23">&times;</span>
        <div class="product-details">
          ...
        </div>
   </div>
</section>
```
Here `data-product-id` attribute shows the ID of the product (which you can _hash_ then) 

The structure is when user clicks on `.close` element to delete that cart item we should instantly get the ID from it's attribute, and the point is to prevent user from changing that ID and finally send the exact true value to the server server.

Lets implement it right now. 😉

AJAX:

```
    $('.close').click(function(){
        const parentID = '#' + $(this).parent().attr('id')
        $(parentID).load(document.URL + ` ${parentID} > *`, function(){
            const pID = $(this).find('.close').attr('data-product-id')
            console.log(pID)
            $.ajax({
                url:url,
                type:'POST',
                data: pID,
                success:function(){alert('Success')},
                error:function(){alert('Error')},
            })
        })
    })
```
As an explanation to this code I have to say, after the user clicks on the `.click` element we get it's parent ID which is unique. Then before the AJAX request, we reset all elements inside this `cart-item` then as a callback function we request to a URL and send the same product ID each time.

You see, even if we change `data-product-id` by inspecting the element in the browser, the console shows the same ID it was in the source code. (I `console.log()` the ID)

**_But Wait!_** there is a tiny bug in this code.

As we reset the `.close` element in jQuery after clicking on it, JavaScript actually creates this element again **dynamically** so we can't click on it over again.

The solution is to involve the document, in this case this problem is easily solved.

```
    $(document).on('click', '.close',function(){
        const parentID = '#' + $(this).parent().attr('id')
        $(parentID).load(document.URL + ` ${parentID} > *`, function(){
            const pID = $(this).find('.close').attr('data-product-id')
            console.log(pID)
            $.ajax({
                url:'index.html',
                type:'POST',
                data: pID,
                success:function(){alert('Success')},
                error:function(){alert('Error')},
            })
        })
    })

```
I hope you enjoyed this post.
Have fun! 😊