I am trying to use Select2 for editing tags for an article. My problem is, that the Tags field in my viewmodel is null when returned to the controller.
An ArticleTag has an Id and a Name field.
ViewModel
public class EditArticleViewModel
{
public Guid Id { get; set; }
public string Header { get; set; }
public string Description { get; set; }
[AllowHtml]
public string Body { get; set; }
public string Image { get; set; }
public bool IsPublished { get; set; }
[UIHint("TagsEditor")]
public IList<ArticleTag> Tags { get; set; }
}
EditArticle view
<div class="form-group">
@Html.LabelFor(model => model.Tags, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Tags)
@Html.ValidationMessageFor(model => model.Tags, "", new {@class = "text-danger"})
</div>
<script type="text/javascript">
$('#tags')
.select2({
data: ["Clare", "Cork", "South Dublin"],
tags: true,
tokenSeparators: [','],
placeholder: "Add your tags here"
});
</script>
Editor template
@model List<MVCForum.Domain.DomainModel.CMS.ArticleTag>
<select id="tags" multiple="multiple" style="width: 100%">
@for (int i = 0; i < Model.Count; i++)
{
<option selected="selected">@Model[i].Name</option>
}
</select>
Now I just can't figure out how to get the data from my Editortemplate/View to the Controller. The List is null when returned.
I have tried to change it to a list of strings instead (in the viewmodel, editortemplate and so on). I have tried to add an editortemplate for the Name field. Same result.
The best thing for me would actually be to get the tags as a comma seperated string. But I just wan't it to work somehow.
A <select multiple>
posts back an array of simple values, not complex objects, so you cannot bind to property IList<ArticleTag> Tags
. Your view model should contain a property to bind to and a property for the options (the following assumes you want to post back the Name
property of each selected ArticleTag
).
public class EditArticleViewModel
{
public Guid Id { get; set; }
....
[Display(Name = "Tags")]
public IEnumerable<string> SelectedTags { get; set; }
public IEnumerable<SelectListItem> TagsList { get; set; }
}
Your GET method would then be
var tags = db.ArticleTag.Select(x => x.Name);
var model = new EditArticleViewModel()
{
TagsList = new SelectList(tags),
SelectedTags = ... // set values to be selected initially if required
};
return View(model);
Then remove your EditorTemplate
and replace it with the strongly typed ListBoxFor()
method so that it binds to your model properties
@Html.ListBoxFor(m => m.SelectedTags, Model.TagsList)
and modify the script to use the id
attribute generated by the ListBoxFor()
method
$('#SelectedTags').select2({
tags: true,
tokenSeparators: [','],
placeholder: "Add your tags here"
});