Коллекция jQuery ломается внутри каждого цикла (удалить элемент, восстановить innerHTML) - PullRequest
0 голосов
/ 01 июня 2018

Я ожидал, что следующий код будет перебирать опции выбора и удалять опции, имеющие определенное значение, в противном случае восстановить HTML выбора

var initialHTML = $('#myselect').html();

$('#myselect option').each(function(){
    if($(this).val() === 'b'){
        $(this).remove();
        console.log('matching. removed.');
        return false;
    }else{
        $('#myselect').html(initialHTML);
        console.log('not matching. html restored.');
    }
});

Ожидаемый выбор будет:

<select id="myselect">
    <option value="a">a</option>
    <option value="c">c</option>
</select>

но на самом деле это

<select id="myselect">
    <option value="a">a</option>
    <option value="b">b</option>
    <option value="c">c</option>
</select>

Что я делаю не так? FIDDLE

Обновление Например, как кто-то предложил:

$('#myselect option') создает список параметров, а $(this).remove() удаляет параметрb, но список параметров больше не связан с HTML, потому что HTML уже был изменен с помощью $('#myselect').html(initialHTML), который был выполнен для опции a

, поэтому я имеюпонял, что актуальная проблема даже не связана с тем, что я изначально задал в своем вопросе.Извините за это, и я постараюсь поместить его в нужный раздел.

ps рабочий раствор :

var initialHTML = $('#myselect').html();

function doIt(){
    $('#myselect').html(initialHTML);

    $('#myselect option').each(function(){
        if($(this).val() === 'b'){
            $(this).remove();
        }
    });
}

Большое спасибо за помощь.

Ответы [ 4 ]

0 голосов
/ 01 июня 2018

Вот альтернативный способ:

Другие ответы уже указывают на причину, поскольку, поскольку вы обновляете список опций во время первой итерации, $(this).remove() больше не работает, потому что теряет контакт с исходным элементом.,Таким образом, простым исправлением здесь будет перевыбор цели на основе ее значения.И вы можете сохранить свой оригинальный код $('#myselect').html(initialHTML); в цикле.

var initialHTML = $('#myselect').html();
$('#myselect option').each(function(){
    if($(this).val() === 'b'){
        $("option[value='" + $(this).val() + "']").remove();
        console.log('matching. removed.');
        return false;
    } else { 
        $('#myselect').html(initialHTML);
        console.log('not matching. html restored.');
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="myselect">
    <option value='a'>a</option>
    <option value='b'>b</option>
    <option value='c'>c</option>
</select>
0 голосов
/ 01 июня 2018

Попробуйте: вам не нужна другая часть, так как она уже есть, и поместите свой jquery в document.ready, чтобы убедиться, что DOM готов, и вы можете запустить скрипт jquery.

var initialHTML = $('#myselect').html();
   $(document).ready(function(){
     $('#myselect option').each(function(){
        if($(this).text() == 'b'){
            $(this).remove();
            console.log('matching. removed.');
            return false;
        }
    });
   });

JSFiddle

0 голосов
/ 01 июня 2018

Основная проблема заключается в следующей строке:

$('#myselect').html(initialHTML);

Она выполняется для опции a, а затем опция b больше не может быть удалена, поскольку HTML-код изменился, даже если он фактически идентичен.Поэтому удалите эту строку, и ваш код будет работать.

$('#myselect option') создает список параметров, а $(this).remove() удаляет параметр b из списка, но список больше не связан с HTML, посколькуHTML уже был изменен на $('#myselect').html(initialHTML), который был выполнен для опции a.

var initialHTML = $('#myselect').html();

$('#myselect option').each(function() {
  if (this.value === 'b') {
    $(this).remove();
    console.log('matching. removed.');
    return false;
  } else {
    //$('#myselect').html(initialHTML);
    console.log('not matching. html restored.');
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="myselect">
  <option>a</option>
  <option>b</option>
  <option>c</option>
</select>

Я изменил $(this).val() на this.value.Оба будут работать, но второй более эффективен, потому что нет смысла преобразовывать объект JavaScript в объект jQuery только для получения значения.

Однако помните, что строка:

return false;

приведет к выходу из цикла each(), как только будет найдено совпадение.Это нормально, если будет только один матч.Если совпадений может быть несколько, удалите эту строку, чтобы цикл мог пройти через все параметры.

0 голосов
/ 01 июня 2018

То, что здесь происходит, это то, что у вас есть что-то, что должно быть ложным только один раз, чтобы восстановить весь выбор.Таким образом, он удаляет «b», когда находит его, но затем восстанавливает весь выбор, когда видит, что «c»! == «b».

Вы можете достичь ожидаемого поведения, удалив:

else{
    $('#myselect').html(initialHTML);
    console.log('not matching. html restored.');
}

В зависимости от того, какова ваша конечная цель, могут быть и лучшие способы достижения этой цели.

Надеюсь, что это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...