Warm tip: This article is reproduced from serverfault.com, please click

How to change the text-content of an html-element as soon as a new option was selected?

发布于 2020-12-02 10:58:10

I am trying to change a span element when a new option is selected in Javascript.

This is the html code:

<span id="month"></span>

(...)
<option id="plan_option".....

And this is my javascript code that currently just displays a text in when the page loads:

window.onload = function month_freq() {
          var id = document.getElementById("plan_option").value;
          var freq = '';
          if (id == 5144746){
            freq = 'ogni mese';
          } else{
            freq = 'ogni due mesi';
          }
          document.getElementById("month").innerHTML = freq;
        }

So, should I make a new function that is called when option changes or idk. Any help is appreciated, thanks!


EDIT

So, I try to set it in more context and update it to the current status.

My goal here is to tell the client, relative to the plan that he chooses, on which basis will he pay (monthly or two monthly). Thanks to @Peter Seliger I updated the code, so I now have this:

Liquid/HTML(1):

<select name="plan_select" id="plan_select">
        {% for plan in selling_plan_group.selling_plans %}
        <option id="plan_option" data-billing-frequency="{% if plan.id == 5144746 %}ogni mese{% else %}ogni due mesi{% endif %}" value="{{ plan.id }}">{{ plan.options[0].value }}</option>
        {% endfor %}
</select>

HTML(2):

<span id="month"></span>

Javascript:

function displayBoundBillingFrequency(evt) {

  const elementSelect = evt.currentTarget;
  if (elementSelect) {

    const selectedOption = elementSelect[elementSelect.selectedIndex];

    // `this` equals the bound billing-frequency display-element.
    this.textContent = (selectedOption.dataset.billingFrequency || '');
  }
}

function mainInit() {

  const planOptions = document.querySelector('#plan_select');
  const frequencyDisplay = document.querySelector('#month');

  if (planOptions && frequencyDisplay) {

    const displayBillingFrequency = displayBoundBillingFrequency.bind(frequencyDisplay);

    // synchronize display data initially.
    displayBillingFrequency({
      currentTarget: planOptions,
    });

    // initialize event listening/handling
    planOptions.addEventListener('change', displayBillingFrequency);
  }
}

mainInit();

But it still doesn't work. Thanks.

Questioner
Benjamin Carafa
Viewed
0
Peter Seliger 2020-12-03 18:02:07

One just wants to listen to the changes of a select element.

Thus one somehow needs to identify this very select element and not so much each of its option elements. The latter one's then do not need to feature either a name- or an id-attribute but a value-attribute instead.

Then one does implement an event handler which does read the currently selected option's value and also does write this very value to the desired/related html-element.

One also needs to provide the event listening/handling to the formerly mentioned select element.

In addition one wants to synchronize the default selected value with the displaying element at load/render time.

Note

For security reasons one does not really want to render a text value via innerHTML ... in this case a textContent write access does the job just fine.

function handleMonthOptionChangeForRelatedDisplay(evt) {

  const elementDisplay = document.querySelector('#month');
  const elementSelect = evt.currentTarget;

  if (elementDisplay && elementSelect) {

    const elementSelect = evt.currentTarget;
    const selectedIndex = elementSelect.selectedIndex;

    elementDisplay.textContent = elementSelect[selectedIndex].value
  }
}

function initMonthOptionChange() {
  const elementSelect = document.querySelector('#month-options');
  elementSelect.addEventListener('change', handleMonthOptionChangeForRelatedDisplay);
}

// window.onload = function () {
//   handleMonthOptionChangeForRelatedDisplay({
//     currentTarget: document.querySelector('#month-options')
//   });
//   initMonthOptionChange();
// }

handleMonthOptionChangeForRelatedDisplay({
  currentTarget: document.querySelector('#month-options')
});
initMonthOptionChange();
<select name="plan_option" id="month-options">
  <option value=""></option>
  <option value="Ogni Mese">ogni mese</option>
  <option value="Ogni due Mesi" selected>ogni due mesi</option>
</select>

<p id="month"></p>

In case the OP has to render an option-specific text-value different from the option element's value-attribute there was still the approach of providing this information via an option-specific data-attribute in order to keep the handler-implementation as generic (without any additional and case-specific compare-logic) as possible ...

function displayBoundBillingFrequency(evt) {

  const elementSelect = evt.currentTarget;
  if (elementSelect) {

    const selectedOption = elementSelect[elementSelect.selectedIndex];

    // `this` equals the bound billing-frequency display-element.
    this.textContent = (selectedOption.dataset.billingFrequency || '');
  }
}

function mainInit() {

  const planOptions = document.querySelector('#plan-options');
  const frequencyDisplay = document.querySelector('#plan-billing-frequency');

  if (planOptions && frequencyDisplay) {

    const displayBillingFrequency = displayBoundBillingFrequency.bind(frequencyDisplay);

    // synchronize display data initially.
    displayBillingFrequency({
      currentTarget: planOptions,
    });

    // initialize event listening/handling
    planOptions.addEventListener('change', displayBillingFrequency);
  }
}

mainInit();
<select name="plan_option" id="plan-options">
  <option value=""></option>
  <option value="541758" data-billing-frequency="ogni mese" selected>First Option</option>
  <option value="752649" data-billing-frequency="ogni due mesi">Second Option</option>
  <option value="invalid">Invalid Option</option>
</select>

<p id="plan-billing-frequency"></p>