Search code examples
javascriptevent-handlingstatetogglebutton

How does one render different text-content depending on a button-element's click-event triggered toggle-state?


I have a button which when clicked, changes the text from 'Report A Problem' to 'Close' & opens a dropdown text input, When the button is clicked again it remains set to 'Close', whereas I would like it to return to 'Report A Problem'. I only know how to trigger 2 events with one click, whereas this would be a two-click action. Any ideas of the best way to approach this?

function change() {
  document.getElementById("myBtnToReportABug").innerHTML = "Close";
}
<button id="myBtnToReportABug" onclick="change()" type="button" class="btn btn-secondary float-right" data-toggle="myModal" data-target="#myModal"> Report A Problem </button>


Solution

  • The biggest advantage of the following approach is that internationalization and localization does not depend on client side JavaScript rendering.

    Since a checkbox is perfectly suited for representing a toggling state, such state depended toggle text just needs to be rendered into two data-* attributes of a checkbox control, which together with an outer label element mimics the behavior of a toggling button.

    All one needs is just HTML and CSS.

    And making the client side script, which is responsible for opening and closing a modal, run on this small component shouldn't be a problem at all ...

    [data-modal-checkbox-button] {
      /* appearance: button; */
      display: inline-block;
      position: relative;
      min-width: 1em;
      padding: 4px;
      text-align: center;
      white-space: nowrap;
      background: #ccc;
      border: 2px solid;
      border-radius: 4px;
      border-style: outset;
    }
    [data-modal-checkbox-button]:active {
      border-style: inset;
    }
    [data-modal-checkbox-button] > [type="checkbox"]:focus {
      outline-offset: 8px;
      outline-color: darkorange;
    }
    [data-modal-checkbox-button]:active > [type="checkbox"] {
      left: -1px;
      top: -1px;  
    }
    
    [data-modal-checkbox-button] > [type="checkbox"] {
      appearance: none;
      display: inline-block;
      position: relative;
    }
    [data-modal-checkbox-button] > [type="checkbox"]::after {
      content: attr(data-checked-false);
    }
    [data-modal-checkbox-button] > [type="checkbox"]:checked::after {
      content: attr(data-checked-true);
    }
    <label data-modal-checkbox-button>
      <input
        name="report-a-bug"
    
        type="checkbox"
        class="btn btn-secondary"
    
        data-toggle="myModal"
        data-target="#myModal"
    
        data-checked-true="Close"
        data-checked-false="Report A Problem"
      />
    </label><br/>
    
    <label data-modal-checkbox-button>
      <input
        name="report-a-bug"
    
        type="checkbox"
        class="btn btn-secondary"
    
        data-toggle="myModal"
        data-target="#myModal"
    
        data-checked-true="Schließen"
        data-checked-false="Ein Problem melden"
      />
    </label><br/>
    
    <label data-modal-checkbox-button>
      <input
        name="report-a-bug"
    
        type="checkbox"
        class="btn btn-secondary"
    
        data-toggle="myModal"
        data-target="#myModal"
    
        data-checked-true="закрывание"
        data-checked-false="Сообщить о проблеме"
      />
    </label>

    In case the OP has to rely on a scripting approach, the OP might consider the following generic and language independent solution ...

    function toggleModalButtonState({ currentTarget }) {
      const { dataset } = currentTarget;
      const { textClose, textReport } = dataset;
    
      const state = (dataset.state === 'close')
        ? 'report'
        : 'close';
        
      dataset.state = state;
    
      currentTarget.textContent = ({
        report: textReport,
        close: textClose,
      })[state];
    }
    document
      .querySelector('#myBtnToReportABug')
      .addEventListener('click', toggleModalButtonState);
    <button
      id="myBtnToReportABug"
    
      type="button"
      class="btn btn-secondary float-right"
    
      data-toggle="myModal"
      data-target="#myModal"
    
      data-state="report"
      data-text-close="Close"
      data-text-report="Report A Problem"
    
    >Report A Problem</button>