Привязка данных в MVC 5 и Select2 Multiple Values с движком Razor
Обычно я очень мало работаю на стороне html приложения, потому что по большей части я просто позволяю этому генерировать для меня.
Я работаю над приложением для блога с сообщениями и комментариями к сообщениям. Что я хочу сделать, так это при создании нового сообщения, я должен иметь возможность добавлять существующие теги в новое сообщение. Я пытаюсь использовать Select2, но я не могу понять, как сделать выбранные значения переданы методу Create в пост-контроллере, чтобы они могли быть сохранены в базе данных.
Вот что я работаю с:
namespace Blog.Data.Entities
{
public class Post
{
public virtual long PostId { get; set; }
-------------------
public virtual ICollection<Tag> Tags { get; set; }
}
public class Tag
{
public virtual long TagId { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
}
}
Почтовый контроллер
// POST: /Post/Create
[HttpPost]
public ActionResult Create(PostsCreateViewModel postModel)
{
if (ModelState.IsValid)
{
Post post = new Post
{
Title = postModel.Title,
Body = postModel.Body,
PostDate = _dateTime.UtcNow
};
foreach (var tag in postModel.Tags)
{
post.Tags.Add(_tagRepository.GetTag(tag.TagId));
}
_postRepository.SavePost(post);
return RedirectToAction("Detail");
}
return View(postModel);
}
Я успешно загружаю данные с удаленного компьютера с помощью: кода Json
<script type="text/javascript">
$(document).ready(function () {
$("#tags").select2(
{
placeholder: "Select a Tag",
minimumInputLength: 1,
multiple: true,
maximumSelectionSize: 5,
ajax: {
url: '@Url.Action("SearchTag", "Post")',
dataType: 'json',
data: function (term, page) {
return {
searchTerm: term,
page_limit: 10,
page: page,
};
},
results: function (data, page) {
var more = (page * 10) < data.total;
return { results: data, more: more };
}
}
});
});
</script>
Вид: обычно у меня было бы что-то вроде
<div class="form-group">
@Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
</div>
Как написать аналогичный html для текстового поля тега, чтобы при нажатии кнопки "Сохранить" все сохраняется в соответствующих таблицах?
В настоящее время у меня есть это только для select2:
<div class="form-group">
@Html.LabelFor(model => model.Tags, new { @class = "control-label col-md-2" })
<div class="col-md-10">
<input id="tags" style="width: 300px" />
@Html.ValidationMessageFor(model => model.Tags)
</div>
</div>
Что производит:
![enter image description here]()
Ответы
Ответ 1
Я также использую select2, и это работает для меня:
Вид
@Html.ListBoxFor(M => M.TagsId, new MultiSelectList(Model.Tags, "Id", "Description"), new { @class = "form-control select-multiple", multiple = "multiple" })
ViewModel
public List<Tag> Tags { get; set; } = new List<Tag>();
public int[] TagsId { get; set; }
Вы можете использовать коллекцию тегов, чтобы заполнить опции в множественном выборе, и массив TagsId будет заполнен идентификатором выбранных тегов. Если вы заполняете опции выбора через ajax, я думаю, вы можете опустить свойство Tags.
Примечание. Я использую множественный выбор, а не текстовое поле.
Ответ 2
Я думаю, что это так же, как <select multiple>
например
<select name="abc" multiple>
<option value=1>a</option>
<option value=2>b</option>
<option value=3>c</option>
<option value=4>d</option>
</select>
вы выбираете вариант a и вариант b, затем отправляете форму методом post
почтовые данные будут
abc 1
abc 2
и вы можете получить данные в действии mvc с параметром вроде IEnumeralbe<int> abc
действие понравится
public ActionResult ActionName(IEnumerable<int> abc)
плагин select2 изменяет только представление, после публикации также используют сообщение http
Ответ 3
Я предлагаю сделать следующее:
-
сначала: сохранить текстовое поле тегов только для отображения.
-
second: есть скрытые входы, которые синхронизируются с значениями текстового поля, манипулируя его значением в javascript. каждый тег в текстовом поле будет иметь скрытый ввод
скрытые входы будут представлять идентификаторы тегов, которые выбраны и показаны в текстовом поле.
Преимущество этого способа заключается в том, что связующее устройство по умолчанию позаботится о привязке значений скрытых входов к свойству модели представления:
[общедоступные виртуальные метки ICollection {get; задавать; }]
расскажите, как скрытые входы должны выглядеть в вашем html:
<input type="hidden" name="Tags[0].TagId" value="1" />
<input type="hidden" name="Tags[1].TagId" value="2" />
<input type="hidden" name="Tags[2].TagId" value="3" />
для получения дополнительной информации о привязке списка просто следуйте по ссылке:
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/
Ответ 4
Если список и выбранные элементы поступают из разных источников:
Пример:
-Model.CategoryList >> фактические элементы selectList
-Model.SubCategories(m => m.SubCategories) >> только выбранные элементы (Ids int [])
@Html.DropDownListFor(m => m.SubCategories, Model.CategoryList, Html.DescriptionFor(m => m.SubCategories), new { @class = "form-control m-select2 select2", multiple = "multiple" })
Я сделал это так с небольшим кодом JS:
@using Newtonsoft.Json;
<script>
//Edit mode
//set "selected" prop for the <select> manaually
$(function () {
var SubCategories_selected = @JsonConvert.SerializeObject(Model.SubCategories);
SubCategories_selected.forEach(function (value, index) {
$('[name="SubCategories"]').find('[value="${value}"]').prop("selected", true);
});
//recall the select2 init
$('#SubCategories').select2();
});
</script>