Как задать выбранный вариант в списке селект в шаблоне Handlebars
Проблема с рендерингом выбранного значения в Handlebars.js
Я использую шаблон Handlebars.js, который выглядит следующим образом:
<select>
<option value="Completed">Completed</option>
<option value="OverDue">OverDue</option>
<option value="SentToPayer">SentToPayer</option>
<option value="None">None</option>
</select>
И у меня есть следующие данные:
{
"id": 1,
"name": "World",
"status": "OverDue",
"date": "2012-12-21"
}
Я хочу отобразить HTML так, чтобы выбранным значением было "OverDue":
<select>
<option value="Completed">Completed</option>
<option value="OverDue" selected="selected">OverDue</option>
<option value="SentToPayer">SentToPayer</option>
<option value="None">None</option>
</select>
Какой самый простой способ выполнить это?
5 ответ(ов)
Я нашёл много сложных решений и решил написать своё собственное, используя помощник Handlebars.
С помощью этого частичного кода (с использованием jQuery) ...
window.Handlebars.registerHelper('select', function(value, options) {
var $el = $('<select />').html(options.fn(this));
$el.find('[value="' + value + '"]').attr({'selected': 'selected'});
return $el.html();
});
Вы можете обернуть ваши выпадающие списки в шаблоне Handlebars с помощью {{#select status}}...
<select>
{{#select status}}
<option value="Completed">Completed</option>
<option value="OverDue">OverDue</option>
<option value="SentToPayer">SentToPayer</option>
<option value="None">None</option>
{{/select}}
</select>
И в итоге получить такой HTML...
<select>
<option value="Completed">Completed</option>
<option value="OverDue" selected="selected">OverDue</option>
<option value="SentToPayer">SentToPayer</option>
<option value="None">None</option>
</select>
Готово!
У меня была аналогичная задача, как у автора вопроса — фиксированный набор опций для выбора, но динамическое выбранное значение. Мне очень понравилось решение @janjarfalk, но я использую Node.js и не подключал jQuery. Поэтому я собрал собственную вариацию, основанную на регулярных выражениях. Надеюсь, это будет полезно другим.
Вот мой хелпер для Handlebars:
hbs.registerHelper('select', function(selected, options) {
return options.fn(this).replace(
new RegExp(' value=\"' + selected + '\"'),
'$& selected="selected"');
});
И соответствующий шаблон Handlebars:
<select>
{{#select CurrentSort}}
<option value="1">Сначала самые новые</option>
<option value="2">Сначала самые старые</option>
<option value="3">Сначала с высоким рейтингом</option>
<option value="4">Сначала с низким рейтингом</option>
<option value="5">Сначала с наибольшим количеством комментариев</option>
<option value="6">Сначала с наименьшим количеством комментариев</option>
<option value="7">Сначала с наиболее полезными голосами</option>
<option value="8">Сначала с наименьшим количеством полезных голосов</option>
{{/select}}
</select>
Вы можете настроить этот хелпер, чтобы он работал даже если вы не используете атрибут value
— достаточно изменить регулярное выражение, чтобы оно искало текст элемента и выполняло замену строки перед совпадающим текстом.
Я увидел очень умное решение, предложенное @janjarfalk, и заметил, что оно не работает для <option>
без атрибута value
(например, <option>Value</option>
). В моем приложении это было необходимо, и я хотел создать хелпер на чистом JavaScript для повышения производительности, поэтому придумал следующее решение.
Это решение поддерживает как <option>Текст и значение</option>
, так и <option value="aValue">Текст</option>
, и будет значительно быстрее, так как не использует jQuery.
Handlebars.registerHelper('select', function(value, options) {
// Создаем элемент select
var select = document.createElement('select');
// Заполняем его HTML-опциями
select.innerHTML = options.fn(this);
// Устанавливаем значение
select.value = value;
// Находим выбранный элемент, если он существует, и добавляем атрибут selected
if (select.children[select.selectedIndex])
select.children[select.selectedIndex].setAttribute('selected', 'selected');
return select.innerHTML;
});
Пример использования:
<select>
{{#select status}}
<option>Опция 1</option>
<option>Опция 2</option>
<option value="Option 3">Опция 3 (дополнительная информация)</option>
<option value="Option 4">Опция 4 (ещё дополнительная)</option>
{{/select}}
</select>
Таким образом, это решение позволяет вам использовать как обычные опции, так и опции с атрибутом value
, сохраняя при этом производительность благодаря отсутствию зависимости от jQuery.
Похоже, ваш код работает корректно. Вот пример, как вы можете его использовать:
<select>
<option value="{{status}}" hidden="hidden" selected="selected">{{status}}</option>
<option value="Completed">Completed</option>
<option value="OverDue">OverDue</option>
<option value="SentToPayer">SentToPayer</option>
<option value="None">None</option>
</select>
Если вы используете шаблонизатор (например, для обработки {{status}}
), убедитесь, что значение status
передается правильно. Если у вас остались вопросы или что-то не работает, пожалуйста, уточните, и я постараюсь помочь!
Проблемы с использованием подхода "select block" и помощника "each" при создании динамических элементов часто возникают из-за контекста. Вот решение, которое может помочь:
Handlebars.registerHelper('option', function(value, label, selectedValue) {
var selectedProperty = value == selectedValue ? 'selected="selected"' : '';
return new Handlebars.SafeString('<option value="' + value + '"' + selectedProperty + '>' + label + "</option>");
});
А вот пример шаблона:
<select>
{{#each status}}
{{option id name ../statusId}}
{{/each}}
</select>
В данном случае, метод option
сравнивает переданное значение (value
) с идентификатором выделенного элемента (selectedValue
). Если они совпадают, добавляется атрибут selected="selected"
. Это позволяет корректно отображать выделенный элемент в выпадающем списке.
Потеряно HTML-кодирование при чтении атрибута из поля ввода
jQuery/JavaScript: Замена битых изображений
Предварительный просмотр изображений перед загрузкой
Как создать WYSIWYG-редактор на HTML/JS? [закрыто]
Как выполнить код после сброса HTML-формы с помощью jQuery?