Skip to content
Advertisement

How to handle if a client change some data attributes from the client side?

<?php foreach ($communities as $community) { ?>
    <div class="community-container">
        <p><?php echo $community->Title ?></p>
        <button class="del-btn" data-id="<?php echo $community->ID ?>">Delete</button>
    </div>
<?php } ?>




<Script>
    const deleteBtns = document.getElementsByClassName('del-btn');
    var deleteBtnsArray = Array.from(deleteBtns);

    deleteBtnsArray.map(deleteBtn => {
        deleteBtn.addEventListener('click', () => {
            const delRequest = new XMLHttpRequest();
            let params = [];
            params = `deleteCommunity=true&communityID=${deleteBtn.dataset.id}`;
            delRequest.open('POST', '/ajax/delete-community');
            delRequest.onreadystatechange = function() {
                if (delRequest.responseText === 'success') {
                    deleteBtn.parentElement.remove();
                }
            }
            delRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            delRequest.send(params);
        })
    })
</Script>

I have communities list on my page and each community item has a delete button. Now when I click on a delete button I want to delete related community item.

But…

I can inspect these delete buttons from the browser and change it’s data-id value to something else(if a data-id of a delete button is 10, I can change it to 1000). Then when I click on that delete button after changing its data-id value from the client side, it will delete some other community instead correct one. (If a community exists with that changed data-id value) because buttons data-id is changed and JavaScript code takes that value to make AJAX request. I can’t stop user changing data-id from the client-side. Therefore, How can I handle this situation if user changed data attributes from client side?

Extra information

$communities is a array of community objects and each community item has a Name and ID.

Advertisement

Answer

You could read the data- prop(s) after the page loads. Store them in an array or whatever and then delete the data- prop(s) from the elements.

Be aware that validation should probably happen somewhere on the server side instead of client side

// Wrap everything in an IIFE so we don't create global variables
(() => {
  const ID_MAP = new WeakMap();

  const onClickAction = ({ currentTarget }) => {
    // Exit if there is no ID stored
    if(!ID_MAP.has(currentTarget)) return;
    
    // Retrieve and log ID
    const id = ID_MAP.get(currentTarget);
    console.log(id);
  }
  
  const btns = document.querySelectorAll('button');
  for(const btn of btns) {
    // Skip if it doesn't have an ID
    if(!btn.dataset.id) continue;

    // Store and hide `data-id` attribute
    ID_MAP.set(btn, btn.dataset.id);
    btn.removeAttribute('data-id');

    // Add event listener
    btn.addEventListener('click', onClickAction, false);
  }
})();
<button data-id="001">id: 001</button>
<button data-id="002">id: 002</button>
<button data-id="003">id: 003</button>
<button data-id="004">id: 004</button>
<button data-id="005">id: 005</button>

EDIT: using suggestions from comments (event delegation)

// Wrap everything in an IIFE so we don't create global variables
(() => {
  const ID_MAP = new WeakMap();

  const onClickAction = ({ target }) => {
    // Exit if it's not a button
    if(target.nodeName !== 'BUTTON') return;
  
    // Exit if there is no ID stored
    if(!ID_MAP.has(target)) return;
    
    // Retrieve and log ID
    const id = ID_MAP.get(target);
    console.log(id);
  }
  
  const btns = document.querySelectorAll('button');
  for(const btn of btns) {
    // Skip if it doesn't have an ID
    if(!btn.dataset.id) continue;

    // Store and hide `data-id` attribute
    ID_MAP.set(btn, btn.dataset.id);
    btn.removeAttribute('data-id');
  }
  
  // Add event listener, instead of `document` you can also use a common parent container
  document.addEventListener('click', onClickAction, false);
})();
<button data-id="001">id: 001</button>
<button data-id="002">id: 002</button>
<button data-id="003">id: 003</button>
<button data-id="004">id: 004</button>
<button data-id="005">id: 005</button>
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement