0

Как задать выбранный вариант в списке селект в шаблоне Handlebars

10

Проблема с рендерингом выбранного значения в 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 ответ(ов)

0

Я нашёл много сложных решений и решил написать своё собственное, используя помощник 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>

Готово!

0

У меня была аналогичная задача, как у автора вопроса — фиксированный набор опций для выбора, но динамическое выбранное значение. Мне очень понравилось решение @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 — достаточно изменить регулярное выражение, чтобы оно искало текст элемента и выполняло замену строки перед совпадающим текстом.

0

Я увидел очень умное решение, предложенное @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.

0

Похоже, ваш код работает корректно. Вот пример, как вы можете его использовать:

<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 передается правильно. Если у вас остались вопросы или что-то не работает, пожалуйста, уточните, и я постараюсь помочь!

0

Проблемы с использованием подхода "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". Это позволяет корректно отображать выделенный элемент в выпадающем списке.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь