为什么我的jquery .on('change')不适用于动态添加的选择

时间:2013-02-18 17:33:00

标签: jquery

我正在动态添加select元素,如下面的HTML。我不确定为什么.on('更改'...)不能用于动态选择。我错过了什么?

我正在使用Chrome 24.0.1312.57 + jquery 1.8.3。

<script type="text/javascript">
  $(document).ready(function() {
      $('#x select').on('change', function () { alert('helo'); })
      $('#y select').on('change', function () { alert('helo'); })

      $('#x').html($('#y').html());
  });
</script>

<div id="x"></div>
<div id="y">
    <select>
        <option>O1</option>
        <option>O2</option>
    </select>
</div>

10 个答案:

答案 0 :(得分:31)

您的代码:

$('#x select').on('change', function () { alert('helo'); })

将一个事件处理程序附加到#x元素内的select。

你想要的东西(根据我所理解的)是符合以下内容的:

$("#y").on('change','select',function () { alert('helo'); });

这将事件处理程序附加到#y元素,该元素被委托给其子元素的“select”元素

来自http://api.jquery.com/on/

  

.on()方法将事件处理程序附加到jQuery对象中当前选定的元素集。

答案 1 :(得分:8)

事件绑定到初始页面加载时不在DOM中的元素将不起作用。您需要绑定到存在的DOM上方的元素,以允许事件向下流动。这通常是我采取的方法:

$(document).on({
  change: function() {
    alert('helo');
  }
}, '#x select');

$(document).on({
  change: function() {
    alert('helo');
  }
}, '#y select');

我更喜欢它,因为您可以轻松添加后续事件。

$(document).on({
  change: function() {
    alert('helo');
  },
  blur: function() {
    alert('helo');
  }
}, '#x select');

答案 2 :(得分:3)

您的事件绑定设置在$(document).ready()上。但是,如果您稍后动态添加它们(例如通过jQuery.appendTo()等),则新添加的组件需要绑定,因为它们不是$(document).ready()中发生的初始组件的一部分。 ,只在加载页面并且最初完成DOM时才运行一次。

答案 3 :(得分:1)

正确的语法:

 $('#x').on(
        'change', 
         'select', 
          function () { 
            alert('helo'); 
          }
       );

因此动态元素on()的语法似乎是:

$(staticParent).on( eventName, target, handler);

答案 4 :(得分:1)

.on()的重点是,您可以将事件绑定到文档以外的其他内容。这就是现在折旧的.live()所做的事情,在大多数情况下都是低效的。您可以将事件绑定到最不会动态更改的父元素。

据我所知,这是正确的语法:

$('#x').on('change', 'select', function(){
    alert('hello');
});

如果要更改#x或#y,请将它们包装在元素上并将事件绑定到该元素。

答案 5 :(得分:1)

这很容易。无论您的目标是什么类别或ID,都要尝试更精确,但不需要包含超级父母。

错误方式的例子:

        $('#tablecontent').on('change', '#tablecontent > table.CampaignGrid > tbody > tr > td', function(e) {
            console.log('IN TABLE CONTENT CHANGE');
            var value = e.target.value;
            $('button#updateLuck').prop('disabled', false).css({'color': '#000', 'font-weight': 600});

            //alert($(ele[0]).html());
        });

正确的方式:

        $('#tablecontent').on('change', 'table.CampaignGrid > tbody > tr > td', function(e) {
            console.log('IN TABLE CONTENT CHANGE');
            var value = e.target.value;
            $('button#updateLuck').prop('disabled', false).css({'color': '#000', 'font-weight': 600});

            //alert($(ele[0]).html());
        });

注意我放弃了超级父母:'#tablecontent'

关于清晰度。

  • V

答案 6 :(得分:1)

/**
 * Source: http://stackoverflow.com/a/33841999/1402846
 *
 * This function is (almost) equivalent to array_column() in PHP (http://php.net/manual/function.array-column.php).
 *
 * Differences between this function and PHP's array_column():
 * <ul>
 *     <li>If <code>indexKey</code> is not found in an element of the input array, the behaviour of this function is undefined.
 *     In PHP's array_column(), the element will be put into the end of the array. It is possible in PHP because PHP does not
 *     distinguish between arrays and dictionaries, but it is not possible in JavaScript because Arrays and Objects are different.
 *
 *     <li>Associative arrays (dictionaries) in PHP are ordered, JavaScript objects are not (http://stackoverflow.com/a/5525820/14028460.
 *     Do not make assumptions on the ordering of the keys in JavaScript objects.
 *
 *     <li>If the value of an element at <code>inputKey</code> is not a string, the result of this function and the PHP function
 *     doesn't make much sense. For example, in PHP,
 *     <code>
 *          $records = array(
 *              array('id' => true, 'last_name' => 'Doe')
 *          );
 *          array_column($records, 'last_name', 'id');
 *     </code>
 *     gives <code>Array([1] => Doe)</code>, or maybe <code>Array([0] => Doe)</code> due to a bug ({@link https://bugs.php.net/bug.php?id=68553}). But, in JavaScript,
 *     <code>
 *          var records = [
 *              {id: true, last_name: 'Doe'},
 *          ];
 *          arrayColumn(records, 'last_name', 'id');
 *     </code>
 *     gives <code>{true: "Doe"}</code>. Therefore, it is strongly advised to make sure that the value at <code>indexKey</code> of
 *     each input element is a string.
 * </ul>
 *
 * @param {Array|Object} inputArray             The input array, it must either contain objects only or arrays only.
 *                                              If it is an object instead of an array, it would be converted to an array first.
 * @param {int|string|null} columnKey           If the input array contains objects, this parameter is the key in each object.
 *                                              If the input array contains arrays, this parameter is the index in each array.
 *                                              If the key or index is not valid, this element is skipped.
 *                                              This parameter may also be <code>null</code>.
 * @param {int|string|null} [indexKey=null]     If the input array contains objects, this parameter must be a valid key in each object.
 *                                              If the input array contains arrays, this parameter must be a valid index in each array.
 *                                              If it is not a valid key or index, the behaviour is undefined.
 *                                              This parameter may also be <code>null</code>.
 * @returns {Array|Object}                      If <code>indexKey</code> is <code>null</code>, this function returns an array which is parallel
 *                                              to the input array. For each element <code>elem</code> in the input array, the element in the
 *                                              output array would be <code>elem[columnKey]</code>, or just <code>elem</code> if <code>columnKey</code>
 *                                              is <code>null</code>.
 *                                              If <code>indexKey</code> is <b>not</b> <code>null</code>, this function returns an object.
 *                                              For each element <code>elem</code> in the input array, the output object would contain an
 *                                              element <code>elem[columnKey]</code>, or just <code>elem</code> if <code>columnKey</code>
 *                                              is <code>null</code>, at the key <code>elem[indexKey]</code>. If the value of <code>elem[indexKey]</code>
 *                                              of some elements in the input array are duplicated, the element in the return object would
 *                                              correspond to the element nearest to the end of the input array.
 * @example
 * var records = [
 *      {id: 2135, first_name: 'John',  last_name: 'Doe'},
 *      {id: 3245, first_name: 'Sally', last_name: 'Smith'},
 *      {id: 5342, first_name: 'Jane',  last_name: 'Jones'},
 *      {id: 5623, first_name: 'Peter', last_name: 'Doe'}
 * ];
 * var first_names = arrayColumn(records, 'first_name');
 * >> ["John", "Sally", "Jane", "Peter"]
 * var last_names = arrayColumn(records, 'last_name', 'id');
 * >> {2135: "Doe", 3245: "Smith", 5342: "Jones", 5623: "Doe"}
 * var persons = arrayColumn(records, null, 'id');
 * >> {
 *      2135: {id: 2135, first_name: 'John',  last_name: 'Doe'},
 *      3245: {id: 3245, first_name: 'Sally', last_name: 'Smith'},
 *      5342: {id: 5342, first_name: 'Jane',  last_name: 'Jones'},
 *      5623: {id: 5623, first_name: 'Peter', last_name: 'Doe'}
 *    }
 */
function arrayColumn(inputArray, columnKey, indexKey)
{
    function isArray(inputValue)
    {
        return Object.prototype.toString.call(inputValue) === '[object Array]';
    }

    // If input array is an object instead of an array,
    // convert it to an array.
    if(!isArray(inputArray))
    {
        var newArray = [];
        for(var key in inputArray)
        {
            if(!inputArray.hasOwnProperty(key))
            {
                continue;
            }
            newArray.push(inputArray[key]);
        }
        inputArray = newArray;
    }

    // Process the input array.
    var isReturnArray = (typeof indexKey === 'undefined' || indexKey === null);
    var outputArray = [];
    var outputObject = {};
    for(var inputIndex = 0; inputIndex < inputArray.length; inputIndex++)
    {
        var inputElement = inputArray[inputIndex];

        var outputElement;
        if(columnKey === null)
        {
            outputElement = inputElement;
        }
        else
        {
            if(isArray(inputElement))
            {
                if(columnKey < 0 || columnKey >= inputElement.length)
                {
                    continue;
                }
            }
            else
            {
                if(!inputElement.hasOwnProperty(columnKey))
                {
                    continue;
                }
            }

            outputElement = inputElement[columnKey];
        }

        if(isReturnArray)
        {
            outputArray.push(outputElement);
        }
        else
        {
            outputObject[inputElement[indexKey]] = outputElement;
        }
    }

    return (isReturnArray ? outputArray : outputObject);
}

        $('#tablecontent').on('change', '#tablecontent > table.CampaignGrid > tbody > tr > td', function(e) {
            console.log('IN TABLE CONTENT CHANGE');
            var value = e.target.value;
            $('button#updateLuck').prop('disabled', false).css({'color': '#000', 'font-weight': 600});

            //alert($(ele[0]).html());
        });

        $('#tablecontent').on('change', '#tablecontent > table.CampaignGrid > tbody > tr > td', function(e) {
            console.log('IN TABLE CONTENT CHANGE');
            var value = e.target.value;
            $('button#updateLuck').prop('disabled', false).css({'color': '#000', 'font-weight': 600});

            //alert($(ele[0]).html());
        });

        $('#tablecontent').on('change', 'table.CampaignGrid > tbody > tr > td', function(e) {
            console.log('IN TABLE CONTENT CHANGE');
            var value = e.target.value;
            $('button#updateLuck').prop('disabled', false).css({'color': '#000', 'font-weight': 600});

            //alert($(ele[0]).html());
        });

答案 7 :(得分:1)

方括号中的单词是alt文本,如果浏览器无法显示图像,则会显示该文本。请务必为屏幕阅读软件添加有意义的替代文字。

答案 8 :(得分:0)

不要使用.live() / .bind() / .delegate()。你应该使用。on()

用于静态和动态选择更改

$(document).on('change', 'select', function (e) {
    // do something 
});

答案 9 :(得分:0)

对此有点误解,因为我无法从动态ID的ajax帖子中返回动态创建的选择来触发事件。

$(document).on('change', 'select', function (e) {
    $("#theDiv select").on("change",function(){ post("SelectChanged");} );
});

直到我先进行一些更改,然后我添加

$("#theDiv select").on("change",function(){ post("SelectChanged");} );

但这并不意味着在更改之后,所有其他更改都会触发两次。 这可能不是很好的做法。 但是我要做的是放入一个在ajax的开始和每次返回时调用的函数。

 `function myFuncs(){
    $('#theDiv select').unbind('change');
    $('#theDiv select').on('change' function(){ post('selectChanged'); });
  }`

但是必须在每个函数调用开始时取消绑定,否则每次都会使函数加倍。 我确信必须有适当的方法来做到这一点,我只是还没有找到它。 感谢您提出问题。