У меня есть CodePen, который загружает cities после выбора country ..., теперь с кодом //$("#country").val("3"); прокомментировано "ручное" изменение страны работает хорошо.
А вот "автоматическая" (код без комментариев) загрузка country не меняет города ... почему?
PS. Я не хочу запускать событие "изменение" вручную. для меня это странно, я должен делать это вручную ...
document.addEventListener("DOMContentLoaded", function(event) {
var countries = {
"1": ["Paris", "Lyon"],
"2": ["Berlin", "Cologne"],
"3": ["London", "Edinburgh"]
};
function loadCities(countryId) {
var cities = countries[countryId];
var container = "#city";
$(container).empty();
$(container).append($("<option/>", { value: 0, text: "select a city..." }));
$.each(cities, function(key, city) {
$(container).append($("<option/>", { text: city }));
});
}
$("#country").on("change", function() {
var countryId = $(this).val();
loadCities(countryId);
});
$("#country").val("3");//.trigger("change");
});<script src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id = "country">
<option value = "0">select a country</option>
<option value = "1">France</option>
<option value = "2">Germany</option>
<option value = "3">UK</option>
</select>
<select id = "city">
<option value = "0">no country selected</option>
</select>Возможный дубликат val () не запускает change () в jQuery
Если вы запустите свой сниппет, появится ошибка "Uncaught ReferenceError: $ is not defined". Если вы измените свой фрагмент на более новую версию jQuery, например 2.x.x, ваш код будет работать. Попробуйте изменить версию jQuery в своем фрагменте.
@PeterB: Я не хочу вручную запускать «изменение».
@Serge Вы должны. Логические изменения не создают событий. События предназначены для взаимодействия с пользователем. Это объясняется в дубликате
@AlexanderStaroselsky: пожалуйста, посмотрите Codepen, странно, почему он не работает, jquery не загружается ...
@Serge, мой первый комментарий к этой теме исправит проблему с ReferenceError.
Пользователь @ Sv443 сделал глупую правку, нарушившую орфографию Edinburgh +, которая удалила библиотеку jQuery. Слишком поздно делать откат, потому что вы уже внесли правку поверх нее (которая затем также будет отменена) ...
@PeterB обновил фрагмент
@ThisGuyHasTwoThumbs исправлено применением предложения Александра
Ничего не сломал. Я просто удалил тег сценария jQuery, потому что он автоматически включен
@ Sv443 в чем проблема с "Эдинбургом"?
Боковая точка. $.each не нужен. Ключ ваших городов - это ваш countryId. Можно просто cities[countryId]
@Serge Я ничего не изменил. Как я уже сказал, я сделал только одно редактирование, и это заключалось в удалении первой строки в разделе HTML, и я изменил версию jQuery в настройках фрагмента. Я даже больше ни на что не нажимал.
Я только что посмотрел исправления, и вы правы, я как-то это изменил. Не знаю, как это случилось, но ладно.
@Taplar для ваших городов [countryId] »отметьте знак« == », это означает, что если ключи являются целыми числами, мы должны сравнивать их по значению, а не по типу ...
Единственная причина, по которой вы это делаете, заключается в том, что вы просматриваете все записи в объекте и пытаетесь найти тот, у которого есть города для countryId. Но это объект. Вы не должны делать это. CountryId - это ключ объекта. Я использовал этот факт в своем ответе ниже
@Taplar я делаю это, потому что в моем реальном примере я получаю целые числа из json в качестве идентификатора, но использую строки в качестве ключа, поэтому «2» и 2 - это не одно и то же, я должен сравнивать «==», а не «===»
то countryId.toString() исправит это. Нет необходимости в петле
@Taplar хороший момент ...



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы также должны вызвать событие change, например:
$("#country").val("3");
$("#country").trigger("change");
onchange срабатывает только тогда, когда пользователь вводит ввод, а затем ввод теряет фокус. Это не может быть действием по умолчанию, поскольку вы не хотите, чтобы событие запускалось из-за автоматического изменения значения, только когда пользователь взаимодействует с элементом.
Причина может заключаться в том, что некоторые люди вызывают .val() в .change(), потому что они выполняют проверку ввода. Запуск .change() на .val() вызовет бесконечный цикл.
Ну, я бы хотел использовать событие "select", может быть ... вместо "change"
вы можете расширить jquery и добавить функцию, скажем, valWithChange, которая будет делать то, что вы хотите.
Или используйте пространство имен, например change.country.
Вы также можете написать это как: $("#country").val("3").change();
Если вы не хотите «инициировать изменение», вы всегда можете вызвать функцию самостоятельно.
function selectCountry(countryId) {
$("#country").val(countryId);
loadCities(countryId)
}
затем замените это:
$("#country").val("3");//.trigger("change");
с этим:
selectCountry("3")
На самом деле это предпочтительнее, так как вы не пропустите свою логику через dom. Вы идете прямо к тому, что хотите делать.
@dovidweisz, просто покажите, пожалуйста, как включить его в реальный код;)
document.addEventListener("DOMContentLoaded", function(event) {
var cities = {
"1": ["Paris", "Lyon"],
"2": ["Berlin", "Cologne"],
"3": ["London", "Edinburgh"]
};
function loadCities(countryId) {
//get the city names if we can
var cityNames = cities[countryId];
//get a reference to the container
var $container = $('#city');
//create an array of the options we want to replace the city with
//building a list of the options allows us to optimize in two ways
//1) Not using jQuery to create the options removes some overhead with
// jQuery creating the DOM nodes one at a time
//2) Replacing all the options at the end reduces the number of times
// you manipulate the DOM and reduce the number of times it has to
// perform calculations about how it is going to re-draw the page
var options = ['<option value = "0">select a city...</option>'];
//we will have cityNames if the countryId is not 0
if (cityNames) {
//make an option for each city
cityNames.forEach(function(city){
options.push('<option>'+ city +'</option>');
});
} else {
//user did not select a country, default the city back to the original
//message
options = ['<option value = "0">no country selected</option>'];
}
//replace all the options with the new options. This will be a single
//DOM change
$container.html(options);
}
$("#country")
//bind the on change like we were before
.on("change", function() {
var countryId = $(this).val();
loadCities(countryId);
})
//also change the value
.val("3");
//call loadCities directly to update the city dropdown
loadCities("3");
});<script src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id = "country">
<option value = "0">select a country</option>
<option value = "1">France</option>
<option value = "2">Germany</option>
<option value = "3">UK</option>
</select>
<select id = "city">
<option value = "0">no country selected</option>
</select>хорошо, но я хочу, чтобы мой "val (" 3 ")" автоматически обновлял значения, если это возможно .. не должно быть необходимости вызывать "loadCities (" 3 ");"
Это уже объяснялось тем фактом, что логические изменения не создают событий.
мое логическое изменение обновляет выбранное значение и текст элемента select. это событие для меня ...
Это не событие для javascript. Вы должны работать с языком.
у вас происходит странная смесь js и jQuery - что происходит, когда вы меняете первую строку на:
jQuery(document).ready(function($) {