Выберите Tag Helper в ASP.NET ядро MVC
мне нужна помощь с помощником select tag в ASP.NET ядро.
у меня есть список сотрудников, которых я пытаюсь привязать к помощнику select tag. Мои сотрудники в List<Employee> EmployeesList
и выбранное значение перейдет в EmployeeId
собственность. Моя модель выглядит так:
public class MyViewModel
{
public int EmployeeId { get; set; }
public string Comments { get; set; }
public List<Employee> EmployeesList {get; set; }
}
мой класс employee выглядит так:
public class Employee
{
public int Id { get; set; }
public string FullName { get; set; }
}
мой вопрос в том, как сказать моему помощнику select tag использовать Id
как значение при отображении FullName
в выпадающем список?
<select asp-for="EmployeeId" asp-items="???" />
Я был бы признателен за помощь в этом. Спасибо.
5 ответов
использование помощников Select Tag для отображения элемента SELECT в вашем представлении
в вашем действии GET создайте объект вашей модели представления, загрузите EmployeeList
свойство коллекции и отправьте его в представление.
public IActionResult Create()
{
var vm = new MyViewModel();
vm.EmployeesList = new List<Employee>
{
new Employee { Id = 1, FullName = "Shyju" },
new Employee { Id = 2, FullName = "Bryan" }
};
return View(vm);
}
и в вашем представлении create создайте новый SelectList
объект EmployeeList
свойство и передать это как значение для asp-items
собственность.
@model MyViewModel
<form asp-controller="Home" asp-action="Create">
<select asp-for="EmployeeId"
asp-items="@(new SelectList(Model.EmployeesList,"Id","FullName"))">
<option>Please select one</option>
</select>
<input type="submit"/>
</form>
и ваш метод действия HttpPost для принятия представленной формы данные.
[HttpPost]
public IActionResult Create(MyViewModel model)
{
// check model.EmployeeId
// to do : Save and redirect
}
или
если ваша модель имеет вид List<SelectListItem>
как свойство для ваших выпадающих элементов.
public class MyViewModel
{
public int EmployeeId { get; set; }
public string Comments { get; set; }
public List<SelectListItem> Employees { set; get; }
}
и в вашем действии get,
public IActionResult Create()
{
var vm = new MyViewModel();
vm.Employees = new List<SelectListItem>
{
new SelectListItem {Text = "Shyju", Value = "1"},
new SelectListItem {Text = "Sean", Value = "2"}
};
return View(vm);
}
и в представлении, вы можете напрямую использовать Employees
свойство asp-items
.
@model MyViewModel
<form asp-controller="Home" asp-action="Create">
<label>Comments</label>
<input type="text" asp-for="Comments"/>
<label>Lucky Employee</label>
<select asp-for="EmployeeId" asp-items="@Model.Employees" >
<option>Please select one</option>
</select>
<input type="submit"/>
</form>
класс SelectListItem
принадлежит Microsoft.AspNet.Mvc.Rendering
пространство имен.
убедитесь, что вы используете явный закрывающий тег для элемента select. Если вы используете в самозакрывания подход таг, вспомогательный тег будет отображаться пустой выберите элемент!
ниже подход не работает
<select asp-for="EmployeeId" asp-items="@Model.Employees" />
но это сработает.
<select asp-for="EmployeeId" asp-items="@Model.Employees"></select>
получение данных из таблицы базы данных с помощью entity framework
в приведенных выше примерах используются жестко закодированные элементы для опций. Поэтому я подумал, что добавлю пример кода для получения данных с использованием Entity framework как много людей использовать это.
предположим, что ваш объект DbContext имеет свойство Employees
типа DbSet<Employee>
здесь Employee
класс сущностей имеет Id
и Name
имущества
public class Employee
{
public int Id { set; get; }
public string Name { set; get; }
}
вы можете использовать запрос linq для получения сотрудников и использовать метод Select в выражении linq для создания списка SelectListItem
предметы для каждого сотрудника.
public IActionResult Create()
{
var vm = new MyViewModel();
vm.Employees = context.Employees
.Select(a => new SelectListItem() {
Value = a.Id.ToString(),
Text = a.Name
})
.ToList();
return View(vm);
}
предполагая, что context
- это объект контекста БД. Код представления такой же, как выше.
Использование SelectList
некоторые люди предпочитают использовать SelectList
класс для хранения элементов, необходимых для отображения параметров.
public class MyViewModel
{
public int EmployeeId { get; set; }
public SelectList Employees { set; get; }
}
теперь в вашем действии GET вы можете использовать SelectList
конструктор для заполнения Employees
свойства модели представления. Убедитесь, что вы указываете dataValueField
и dataTextField
параметры.
public IActionResult Create()
{
var vm = new MyViewModel();
vm.Employees = new SelectList(GetEmployees(),"Id","FirstName");
return View(vm);
}
public IEnumerable<Employee> GetEmployees()
{
return new List<Employee>
{
new Employee { Id=1, FirstName="Shyju"},
new Employee { Id=2, FirstName="Bryan"}
};
}
вот я вызываю GetEmployees
метод для получения списка объектов Employee, каждый с Id
и FirstName
property и я использую эти свойства как DataValueField
и DataTextField
на SelectList
объект, который мы создали. Вы можете изменить жестко закодированный список на код, который считывает данные из таблицы базы данных.
код представления будет таким же.
<select asp-for="EmployeeId" asp-items="@Model.Employees" >
<option>Please select one</option>
</select>
отображение элемента SELECT из списка строк.
иногда может потребоваться отобразить элемент select из списка строк. В этом случае, вы можете использовать SelectList
конструктор, который принимает только IEnumerable<T>
var vm = new MyViewModel();
var items = new List<string> {"Monday", "Tuesday", "Wednesday"};
vm.Employees = new SelectList(items);
return View(vm);
код представления будет таким же.
настройка выбранных параметров
иногда вы можете установить один параметр в качестве параметра по умолчанию в элементе SELECT (например, на экране редактирования вы хотите загрузить ранее сохраненное значение параметра). Для этого вы можете просто установить EmployeeId
значение свойства для значения параметра, который вы хотите выбрать.
public IActionResult Create()
{
var vm = new MyViewModel();
vm.Employees = new List<SelectListItem>
{
new SelectListItem {Text = "Shyju", Value = "11"},
new SelectListItem {Text = "Tom", Value = "12"},
new SelectListItem {Text = "Jerry", Value = "13"}
};
vm.EmployeeId = 12; // Here you set the value
return View(vm);
}
это позволит выбрать опция Tom в элементе select при отображении страницы.
Multi выберите выпадающее меню
если вы хотите отобразить раскрывающийся список multi select, вы можете просто изменить свойство модели представления, которое вы используете для asp-for
атрибут в представлении к типу массива.
public class MyViewModel
{
public int[] EmployeeIds { get; set; }
public List<SelectListItem> Employees { set; get; }
}
это отобразит разметку HTML для элемента select с помощью multiple
атрибут, который позволит пользователю выбрать несколько параметров.
@model MyViewModel
<select id="EmployeeIds" multiple="multiple" name="EmployeeIds">
<option>Please select one</option>
<option value="1">Shyju</option>
<option value="2">Sean</option>
</select>
настройка выбранные параметры в multi select
подобно single select, установите EmployeeIds
значение свойства для массива значений, которые вы хотите.
public IActionResult Create()
{
var vm = new MyViewModel();
vm.Employees = new List<SelectListItem>
{
new SelectListItem {Text = "Shyju", Value = "11"},
new SelectListItem {Text = "Tom", Value = "12"},
new SelectListItem {Text = "Jerry", Value = "13"}
};
vm.EmployeeIds= new int[] { 12,13} ;
return View(vm);
}
это позволит выбрать опцию Tom и Jerry в элементе multi select при отображении страницы.
использование ViewBag для передачи списка элементов
если вы не хотите сохранять свойство типа коллекции для передачи списка параметров в представление, вы можете использовать динамический ViewBag для этого.(это не мой лично рекомендуемый подход, поскольку viewbag динамичен, и ваш код склонен к неперехваченным ошибкам опечатки)
public IActionResult Create()
{
ViewBag.Employees = new List<SelectListItem>
{
new SelectListItem {Text = "Shyju", Value = "1"},
new SelectListItem {Text = "Sean", Value = "2"}
};
return View(new MyViewModel());
}
и
<select asp-for="EmployeeId" asp-items="@ViewBag.Employees">
<option>Please select one</option>
</select>
группировки элементов
вспомогательный метод select tag поддерживает параметры группировки в раскрывающемся списке. Все, что вам нужно сделать, это указать Group
значение свойства каждого SelectListItem в методе действия.
public IActionResult Create()
{
var vm = new MyViewModel();
var group1 = new SelectListGroup { Name = "Dev Team" };
var group2 = new SelectListGroup { Name = "QA Team" };
var employeeList = new List<SelectListItem>()
{
new SelectListItem() { Value = "1", Text = "Shyju", Group = group1 },
new SelectListItem() { Value = "2", Text = "Bryan", Group = group1 },
new SelectListItem() { Value = "3", Text = "Kevin", Group = group2 },
new SelectListItem() { Value = "4", Text = "Alex", Group = group2 }
};
vm.Employees = employeeList;
return View(vm);
}
нет никаких изменений в код вида. помощник select tag теперь отобразит параметры внутри 2 optgroup предметы.
Я создал интерфейс и <options>
tag helper для этого. Поэтому мне не пришлось преобразовывать IEnumerable<T>
предметы IEnumerable<SelectListItem>
каждый раз, когда я должен заполнить <select>
управление.
и я думаю, что это прекрасно работает...
использование что-то вроде:
<select asp-for="EmployeeId">
<option value="">Please select...</option>
<options asp-items="@Model.EmployeesList" />
</select>
и чтобы заставить его работать с помощью тега вы должны реализовать этот интерфейс в классе:
public class Employee : IIntegerListItem
{
public int Id { get; set; }
public string FullName { get; set; }
public int Value { return Id; }
public string Text{ return FullName ; }
}
вот код:
в интерфейс:
public interface IIntegerListItem
{
int Value { get; }
string Text { get; }
}
на <options>
tag helper:
[HtmlTargetElement("options", Attributes = "asp-items")]
public class OptionsTagHelper : TagHelper
{
public OptionsTagHelper(IHtmlGenerator generator)
{
Generator = generator;
}
[HtmlAttributeNotBound]
public IHtmlGenerator Generator { get; set; }
[HtmlAttributeName("asp-items")]
public object Items { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.SuppressOutput();
// Is this <options /> element a child of a <select/> element the SelectTagHelper targeted?
object formDataEntry;
context.Items.TryGetValue(typeof(SelectTagHelper), out formDataEntry);
var selectedValues = formDataEntry as ICollection<string>;
var encodedValues = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
if (selectedValues != null && selectedValues.Count != 0)
{
foreach (var selectedValue in selectedValues)
{
encodedValues.Add(Generator.Encode(selectedValue));
}
}
IEnumerable<SelectListItem> items = null;
if (Items != null)
{
if (Items is IEnumerable)
{
var enumerable = Items as IEnumerable;
if (Items is IEnumerable<SelectListItem>)
items = Items as IEnumerable<SelectListItem>;
else if (Items is IEnumerable<IIntegerListItem>)
items = ((IEnumerable<IIntegerListItem>)Items).Select(x => new SelectListItem() { Selected = false, Value = ((IIntegerListItem)x).Value.ToString(), Text = ((IIntegerListItem)x).Text });
else
throw new InvalidOperationException(string.Format("The {2} was unable to provide metadata about '{1}' expression value '{3}' for <options>.",
"<options>",
"ForAttributeName",
nameof(IModelMetadataProvider),
"For.Name"));
}
else
{
throw new InvalidOperationException("Invalid items for <options>");
}
foreach (var item in items)
{
bool selected = (selectedValues != null && selectedValues.Contains(item.Value)) || encodedValues.Contains(item.Value);
var selectedAttr = selected ? "selected='selected'" : "";
if (item.Value != null)
output.Content.AppendHtml($"<option value='{item.Value}' {selectedAttr}>{item.Text}</option>");
else
output.Content.AppendHtml($"<option>{item.Text}</option>");
}
}
}
}
может быть какая-то опечатка, но цель ясна, я думаю. Мне пришлось немного отредактировать.
вы также можете использовать IHtmlHelper.GetEnumSelectList.
// Summary:
// Returns a select list for the given TEnum.
//
// Type parameters:
// TEnum:
// Type to generate a select list for.
//
// Returns:
// An System.Collections.Generic.IEnumerable`1 containing the select list for the
// given TEnum.
//
// Exceptions:
// T:System.ArgumentException:
// Thrown if TEnum is not an System.Enum or if it has a System.FlagsAttribute.
IEnumerable<SelectListItem> GetEnumSelectList<TEnum>() where TEnum : struct;
вы можете использовать ниже код множественный выбор:
<select asp-for="EmployeeId" multiple="multiple" asp-items="@ViewBag.Employees">
<option>Please select</option>
</select>
вы также можете использовать:
<select id="EmployeeId" name="EmployeeId" multiple="multiple" asp-items="@ViewBag.Employees">
<option>Please select</option>
</select>
В Get : // ПОЛУЧИТЬ: public IActionResult создать() {
ViewData["Tags"] = new SelectList(_context.Tags, "Id", "Name");
return View();
}
В Должности : var selectedIds= запрос.Форма ["Теги"];
В Виде :
<label>Tags</label>
<select asp-for="Tags" id="Tags" name="Tags" class="form-control" asp-items="ViewBag.Tags" multiple></select>