0

When I try to rename my object "on click" via Ajax request and then try to update its element's attribute with this new name via Ajax success function, it doesn't fully work.

As I inspect the element in question with chrome, I can see that the attribute has indeed been updated after Ajax, but when I try to log this attribute "on click" again, it outputs the old value, and not the updated one. Only when I manually refresh the page, the updated value gets logged.

HTML rename icon:

This triggers a popover with input field when clicked on:

<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
    class="bi bi-pen-fill rename-add-icon rename-icon-sidebar" 
    data-bs-placement="top" data-sender="board" 
    data-action="rename" data-placeholder="" 
    data-value="{{ board.name }}" data-id="{{ board.id }}" 
    viewBox="0 0 16 16"> 
    <path d="m13.498.795.149-.149a1.207 1.207 0 1 1 1.707 1.708l-.149.148a1.5 1.5 0 0 1-.059 2.059L4.854 14.854a.5.5 0 0 1-.233.131l-4 1a.5.5 0 0 1-.606-.606l1-4a.5.5 0 0 1 .131-.232l9.642-9.642a.5.5 0 0 0-.642.056L6.854 4.854a.5.5 0 1 1-.708-.708L9.44.854A1.5 1.5 0 0 1 11.5.796a1.5 1.5 0 0 1 1.998-.001z" />

Javascript / jQuery:

function renameAddPopover() {
  $('.rename-add-icon').popover({
    html: true,
    sanitize: false,
    content: function () {
      return '<input class="card bg-dark text-light add-input" type="text" placeholder="' + $(this).data("placeholder") + '" value="' + $(this).data("value") + '" />'
    },
    // focus the input and put the prompt at the end of text
  }).on('shown.bs.popover', function () {

    var input = $('.add-input');
    var strLength = input.val().length;
    input.focus();
    input[0].setSelectionRange(strLength, strLength);

  });
}

function ajaxBoardManager(action, id, entered_name){
  // Post the data
  $.ajax({
    type: "POST",
    url: 'http://localhost:8000/board_manager/',
    data: {
      name: entered_name,
      id: id,
      action: action,
      csrfmiddlewaretoken: getCookie('csrftoken'),
    },
    datatype: 'json',

    success: function (json) {

      if (action == 'rename'){
        // Update the name
        $('.board-item[value="'+id+'"]').html(json.name)

        // Update the rename-add-icon's data-value attribute, so when clicking on rename again
        // the input field gets pre-populated with this new name
        $('.rename-add-icon[data-id="'+id+'"]').attr('data-value', json.name)

        console.log($('.rename-add-icon[data-id="'+id+'"]').attr('data-value'))
      }
    },
    error: function (xhr, errmsg, err) {
    },
  });
}

$(document).ready(function () {
  // initialize the popover
  renameAddPopover();
  
  // RENAME OR ADD ICON
  $('.rename-add-icon').on('click', function () {
  
    sender = $(this).data('sender');
    action = $(this).data('action');
    id = $(this).data('id');
  
    value = $(this).data('value');
    placeholder = $(this).data('placeholder');
  
    console.log(value)
    
    renameAddPopover();
  
    // On pressing Enter
    $(".add-input").keypress(function (e) {
      if (e.which === 13) {
        // only if something is entered
        if ($('.add-input').val()) {
          e.preventDefault();
  
          entered_name = $(this).val();
  
          $('.rename-add-icon').popover('hide');
  
          if (sender == 'board') {
            ajaxBoardManager(action, id, entered_name)
          }
        }
      }
    });
  });
});
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Luka Reeson
  • 113
  • 12
  • After first ajax on success refresh the function $('.rename-add-icon').on('click',... – Weber Jun 21 '21 at 12:30
  • Really bad practice adding event listeners inside other event handlers. If you click more than once you add a new event listener each time – charlietfl Jun 21 '21 at 12:41
  • Does this answer your question? [jQuery Data vs Attr?](https://stackoverflow.com/questions/7261619/jquery-data-vs-attr) – freedomn-m Jun 21 '21 at 12:56
  • 1
    When you use `.data("name")` it stores it in memory, changing the html with `.prop("data-name", val)` does *not* change the stored value. if you're using `.data()` then **always use** `.data()` - ie `.data("name", val)` – freedomn-m Jun 21 '21 at 12:57
  • @charlietfl you mean all those "on" events? What would be the best way to restructure the code then? – Luka Reeson Jun 21 '21 at 13:03
  • No I mean the `keypress` inside `click`. Move it outside the click handler – charlietfl Jun 21 '21 at 13:14
  • I see, cuz the keypress is always listening, right? Still learning :) – Luka Reeson Jun 21 '21 at 13:21
  • 1
    If you click once... it sets up a key listener. Click twice it adds another one, third click 3 listeners etc – charlietfl Jun 21 '21 at 13:23
  • Hmm..weird. I moved keypress out of click, and now when I press Enter nothing happens. EDIT: Had to replace "$(.add-input').keypress(function (e)" with "$(document).keypress('.add-input', function (e)" – Luka Reeson Jun 21 '21 at 13:29

1 Answers1

1

I believe the issue is that when you update an .attr or a .prop it does not automatically update the value in .data

Try changing...

$('.rename-add-icon[data-id="'+id+'"]').attr('data-value', json.name)

To...

$('.rename-add-icon[data-id="'+id+'"]').data('value', json.name)
freefaller
  • 19,368
  • 7
  • 57
  • 87