【问题标题】:Javascript: script for menu not reacting when menu is dynamically createdJavascript:菜单脚本在动态创建菜单时没有反应
【发布时间】:2019-01-30 00:06:39
【问题描述】:

我有这个菜单,静态的如下:

<div class="dropdown col-sm-3">
        <button type="button" 
            class="btn btn-select btn-block"
            data-toggle="dropdown">Plane <span class="caret"></span>
        </button>
        <ul class="dropdown-menu dropdown-menu-select" id="plane">
            <li><label class="dropdown-radio"> <input type="radio" value="3" name="plane"> Plane: A360 </label></li>
            <li><label class="dropdown-radio"> <input type="radio" value="2" name="plane"> Plane: AR45 </label></li>
            <li><label class="dropdown-radio"> <input type="radio" value="1" name="plane"> Plane: A380 </label></li>
        </ul>
    </div>
...

<script>
    $('.dropdown-radio').find('input').change(function() {
      var dropdown = $(this).closest('.dropdown');
      var radioname = $(this).attr('name');
      var checked = 'input[name=' + radioname + ']:checked';

      //update the text
      var checkedtext = $(checked).closest('.dropdown-radio').text();
      dropdown.find('button').text( checkedtext );

      //retrieve the checked value, if needed in page 
      var thisvalue = dropdown.find( checked ).val();
      console.log( thisvalue );
    });
</script>

此版本有效:用户可以选择一个(并且只有一个)选项,然后该选项将显示在主按钮中。我现在已经使用 MySQL 数据库中的数据动态创建了相同的菜单。

<script>
var socket = io.connect('http://localhost:3000');

socket.on('sess', function(message) {

if(message == 0){
    alert('No planes associated.');
}else{
    for(var i = 0; i < message.length; i++){
        $('#session').prepend( '<li><label class="dropdown-radio" > <input type="radio" value="' 
        + message[i].idSession + '" name="session"> Session: ' 
        + message[i].idSession + ' </label></li>');
    }
    }
});
</script>

这里的菜单仍然下拉,但现在用户可以根据需要检查任意数量的收音机,并且第一个脚本没有被激活(控制台中没有任何内容)。我尝试将第二个脚本放在前一个脚本之前和之后,都给出相同的结果。

有解决办法吗?我是 Javascript (jQuery) 及其敏感性的新手。

谢谢

【问题讨论】:

  • 这可能与您的脚本在从数据库中检索数据之前运行的事实有关,它应该在添加新收音机后运行,尝试将第一个脚本包装在一个函数中并调用它socket.on 函数结束
  • 第一个脚本在页面加载的内联运行一次,并且由于对您的数据库的异步调用,这意味着它找不到任何可以将change 绑定到的脚本,然后该脚本将不再运行.您需要更新您的脚本,以便在 新的单选按钮全部加载到 DOM 之后再次运行它(这是在 time 之后,而不是在页)。
  • 考虑将您的第一个脚本保存到一个函数并从您的数据库调用成功中调用它,然后渲染您的单选按钮。您可能还需要使用 .off('change') 来删除任何现有的更改绑定,然后再创建新绑定。
  • 顺便说一句,最好在标签或描述上提及jquery,它在任何地方都不明确。不知道 jquery api 的人会不确定。

标签: javascript jquery html radio-button


【解决方案1】:

您想要的是将更改事件绑定到更高层次的元素,而不是直接绑定到尚不存在的输入:

$('#plane').on('change', 'input', function() {
      var dropdown = $(this).closest('.dropdown');
      var radioname = $(this).attr('name');
      var checked = 'input[name=' + radioname + ']:checked';

      //update the text
      var checkedtext = $(checked).closest('.dropdown-radio').text();
      dropdown.find('button').text( checkedtext );

      //retrieve the checked value, if needed in page 
      var thisvalue = dropdown.find( checked ).val();
      console.log( thisvalue );
    });

这样做,您将 change 事件绑定到父 div,因此无论您稍后如何修改其子元素,如果目标元素是 @987654323,它将始终为它触发事件@(第二个函数参数)。

您无需在加载输入后执行此脚本,只需按照您的初始方法动态加载内容,但使用 on('change' 版本调整 change

【讨论】:

    【解决方案2】:

    我已将我的 cmets 组合成一个答案,以便于阅读/供其他人查看。


    第一个脚本在页面加载时运行一次,并且由于对数据库的异步调用,这意味着它找不到任何可以将change 绑定到的内容,然后该脚本将不再运行。您需要更新您的脚本,以便在新的单选按钮全部加载到 DOM 之后 再次运行它(这是在 时间 之后,而不是在页)。

    考虑将您的第一个脚本保存到一个函数并从您的数据库调用成功中调用它,然后渲染您的单选按钮。您可能还需要使用 .off('change') 来删除任何现有的更改绑定,然后再创建新绑定。

    关于您的单选按钮允许多选,只要它们共享name,那么根据documentation,它们不应该允许多选。

    【讨论】: