Как установить выбранную опцию выбора в шаблоне Handlebars
С шаблоном 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 таким образом.
<select>
<option value="Completed">Completed</option>
<option value="OverDue" selected="selected">OverDue</option>
<option value="SentToPayer">SentToPayer</option>
<option value="None">None</option>
</select>
Какой путь самый простой?
Ответы
Ответ 1
Я нашел много сложных решений и решил написать свой собственный с помощью помощника 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>
и в конечном итоге с этим...
<select>
<option value="Completed">Completed</option>
<option value="OverDue" selected="selected">OverDue</option>
<option value="SentToPayer">SentToPayer</option>
<option value="None">None</option>
</select>
Presto!
Ответ 2
У меня была аналогичная потребность в OP - со статическим набором параметров выбора, но с динамическим выбранным значением. Мне очень нравится решение @janjarfalk, но я использую node.js и не вставляю jQuery. Итак, я собрал свои собственные варианты, основанные на RegExp. Надеюсь, что это полезно для других.
Помощник 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">Most Recent First</option>
<option value="2">Most Recent Last</option>
<option value="3">Highest Score First</option>
<option value="4">Highest Score Last</option>
<option value="5">Most Comments</option>
<option value="6">Fewest Comments</option>
<option value="7">Most Helpful Votes</option>
<option value="8">Fewest Helpful Votes</option>
{{/select}}
</select>
Вы можете настроить помощника на работу, даже если вы не используете атрибут value
- просто настройте регулярное выражение для поиска текста элемента и выполните замену строки перед совпадающим текстом.
Ответ 3
Я увидел чрезвычайно умное решение, отправленное @janjarfalk, и понял, что он не работает для опций, определенных без атрибута value (например, <option>Value</option>
). Мое приложение нуждалось в этом, и я хотел, чтобы хелпер, выполненный в ванильном JavaScript для производительности, поэтому я придумал следующее.
Это решение будет поддерживать <option>Both a label and a value</option>
в дополнение к <option value="aValue">A label</option>
и будет намного быстрее, поскольку оно не использует jQuery.
Handlebars.registerHelper('select', function(value, options) {
// Create a select element
var select = document.createElement('select');
// Populate it with the option HTML
select.innerHTML = options.fn(this);
// Set the value
select.value = value;
// Find the selected node, if it exists, add the selected attribute to it
if (select.children[select.selectedIndex])
select.children[select.selectedIndex].setAttribute('selected', 'selected');
return select.innerHTML;
});
Использование:
<select>
{{#select status}}
<option>Option 1</option>
<option>Option 2</option>
<option value="Option 3">Option 3 (extra info)</option>
<option value="Option 4">Option 4 (more extra)</option>
{{/select}}
</select>
Ответ 4
У меня были проблемы с подходом "select block" при использовании "каждого" помощника для создания чего-то динамического из-за контекста.
Вот мое решение:
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>
Ответ 5
Улучшен ответ @lazd, чтобы выбрать первый вариант, когда ничего не соответствует.
Handlebars.registerHelper('select', function(value, options) {
// Create a select element
var select = document.createElement('select');
// Populate it with the option HTML
$(select).html(options.fn(this));
//below statement doesn't work in IE9 so used the above one
//select.innerHTML = options.fn(this);
// Set the value
select.value = value;
// Find the selected node, if it exists, add the selected attribute to it
if (select.children[select.selectedIndex]) {
select.children[select.selectedIndex].setAttribute('selected', 'selected');
} else { //select first option if that exists
if (select.children[0]) {
select.children[0].setAttribute('selected', 'selected');
}
}
return select.innerHTML;
});
Использование остается таким же:
<select>
{{#select status}}
<option>Option 1</option>
<option>Option 2</option>
<option value="Option 3">Option 3 (extra info)</option>
<option value="Option 4">Option 4 (more extra)</option>
{{/select}}
</select>
Ответ 6
Я просто столкнулся с этой проблемой, вот решение, когда параметры динамические.
Вместо создания вспомогательного элемента select я создал вспомогательный параметр, который принимает значение элемента, который вы хотите выбрать.
Handlebars.registerHelper('option', function(value) {
var selected = value.toLowerCase() === (this.toString()).toLowerCase() ? 'selected="selected"' : '';
return '<option value="' + this + '" ' + selected + '>' + this + '</option>';
});
И в моем шаблоне.
{{#items}}
{{{option ../selected_value}}}
{{/items}}
Обратите внимание, что../для доступа к родительской области, так как это вряд ли будет выбрано_значение будет внутри массива элементов.
Приветствия.
Ответ 7
Я предпочитаю использовать шаблонный подход. Под этим я подразумеваю, что макет самого тега параметра задается в шаблоне дескрипторов (где кто-то может его искать), а не в помощнике javascript. Шаблон внутри вспомогательного блока передается в помощник script и может быть использован при вызове options.fn(), который затем использует любые изменения script, внесенные вами в ваш помощник.
Шаблон:
<select>
{{#optionsList aStatusList sCurrentStatusCode 'statusCode'}}
<option {{isSelected}} value="{{statusCode}}">{{statusName}}</option>
{{/optionsList}}
</select>
Немного измененные данные (не требуются, но немного больше "реальный мир" для меня)
var myOrder =
{
"id" : 1,
"name" : "World",
"statusName" : "OverDue", /* status should NOT be here! */
"statusCode" : "1",
"date" : "2012-12-21"
}
var sCurrentStatusCode = myOrder.statusCode;
var aStatusList =
[
{
"statusName" : "Node",
"statusCode" : 0
},
{
"statusName" : "Overdue",
"statusCode" : 1
},
{
"statusName" : "Completed",
"statusCode" : 2
},
{
"statusName" : "Sent to Payer",
"statusCode" : 3
}
]
Зарегистрированный Javascript помощник:
Handlebars.registerHelper( 'optionsList',
function ( aOptions, sSelectedOptionValue, sOptionProperty, options )
{
var out = "";
for ( var i = 0, l = aOptions.length; i < l; i++ )
{
aOptions[ i ].isSelected = '';
if( ( sOptionProperty != null && sSelectedOptionValue == aOptions[ i ][ sOptionProperty ] ) || ( sSelectedOptionValue == aOptions[ i ] ) )
{
aOptions[ i ].isSelected = ' selected="selected" ';
}
out = out + options.fn( aOptions[ i ] );
}
return out;
} );
optionsList - это то, что я выбрал, чтобы назвать этот помощник
aStatusList массив объектов состояния содержит несколько свойств, включая статус/имя состояния (в большинстве случаев я столкнулся с этим, это будет код состояния, а не имя состояния, которое сохраняется)
sCurrentStatus - это ранее выбранный код состояния (а не значение) и является значением параметра, которое я хотел бы иметь в этом сгенерированном списке опций.
statusCode - это имя свойства строки в объекте aStatusList, который будет проверяться, если он соответствует myStatus, который является aStutusList [loopIndex] [ statusCode]
- Свойство опции строки (statusCode в этом случае) требуется только для списков объектов - вариантов также могут быть массивы строк (вместо объектов, которые, в свою очередь, содержат строки), и в этом случае вы можете опустить третье свойство 'statusCode ', который сообщает помощнику, какое свойство объекта проверять снова. Если вы не передадите это свойство, он просто проверит снова элемент списка.
- Если sSelectedOptionValue не передается, список будет создан без установки какого-либо элемента в выбранный. Это приведет к созданию списка почти так же, как с помощью {{# each}} помощника
Ответ 8
Если у вас очень мало вариантов, и вы не хотите писать помощника, вот что вы можете сделать:
//app.js
var data = {selectedVal: 'b'};
// can also use switch ... case ...
if (data.selectedVal === 'a') {
data.optionASelected = true;
} else if (data.selectedVal === 'b') {
data.optionBSelected = true;
}
// assuming you have a template function to handle this data
templateFunc(data);
В файле шаблона:
<!-- template.html -->
<select id="select-wo-helper" >
<option value="a" {{#if optionASelected}} selected {{/if}}>A</option>
<option value="b" {{#if optionBSelected}} selected {{/if}}>B</option>
</select>
Опять же, это НЕ может быть лучшим решением для всех, но, вероятно, это очень быстрая работа, когда вы имеете дело с несколькими вариантами и хотели бы быстро исправить.
Ответ 9
Работает для меня
<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>
Ответ 10
Следует отметить, что если вам не нужны повторы... вы можете просто использовать ванильные рули и сначала поместить выбранный параметр, например:
<select name="ingredient">
<option value="{{ingredient.id}}" selected>{{ingredient.name}}</option>
{{#each ingredients}}
<option value="{{this.id}}">{{this.name}}</option>
{{/each}}
</select>
Ответ 11
@lazd ответ не работает для <option>
элементов в <optgroup>
.
selectedIndex
пронумерована монотонно для всех <option>
s, но select.children
содержит <optgroup>
s, а select.children[n].children
содержит <option>
внутри <optgroup>
n (с перезапуском нумерации в каждом <optgroup>
, конечно).
Эта альтернативная версия будет работать для <option>
элементов внутри <optgroup>
s:
Handlebars.registerHelper('select-optgrp', function(value, options) {
var select = document.createElement('select'); // create a select element
select.innerHTML = options.fn(this); // populate it with the option HTML
select.value = value; // set the value
var g = 0, i = select.selectedIndex; // calculate which index of which optgroup
while (i >= select.children[g].children.length) { i -= select.children[g].children.length; g++; }
if (select.children[g].children[i]) { // if selected node exists add 'selected' attribute
select.children[g].children[i].setAttribute('selected', true);
}
return select.innerHTML;
});
Ответ 12
Это может занять больше кода в шаблоне, но его легче читать:
.js
Handlebars.registerHelper('select', function(selected, option) {
return (selected == option) ? 'selected="selected"' : '';
});
.hbs
<select name="status">
<option value="public" {{{select story.status 'public'}}}>Public</option>
<option value="private" {{{select story.status 'private'}}}>Private</option>
<option value="unpublished" {{{select story.status 'unpublished'}}}>Unpublished</option>
</select>
Ответ 13
Еще одно решение с использованием express-handlebars
и динамических параметров.
Функция помощника (из всех параметров берем тот, который мы хотим, и меняем его на выбранный).
select: function(selected, options) {
return options.fn(this)
.replace( new RegExp(' value=\"' + selected + '\"'), '$& selected="selected"')
.replace( new RegExp('>' + selected + '</option>'), ' selected="selected"$&');
}
файл handlebars (я просто использую #each внутри select, чтобы получать данные и работать как шарм).
<select name="justAname">
{{#select content.campusId}}
{{#each campus}}
<option value="{{id}}">{{name}}</option>
{{/each}}
{{/select}}
</select>