【问题标题】:Add items to select list on the client side in MVC 5 ASP在 MVC 5 ASP 的客户端添加项目以选择列表
【发布时间】:2016-01-02 03:55:09
【问题描述】:

我正在尝试了解有关 MVC 5 的更多信息,因此我正在为自己编写一个博客网站,以便在我学习的过程中了解更多信息。

我已经为标签设置了一个选择列表,并且希望能够从创建博客条目页面添加新标签,而不必记住在创建新帖子之前设置标签。我正在考虑“添加标签”按钮的线条,该按钮显示一个引导模式窗口,用户可以在其中添加新标签。

这是我的控制器操作:

public ViewResult CreateBlogPost()
{
    CreateEditBlogViewModel viewModel = new CreateEditBlogViewModel();
    viewModel.BlogPost = new Core.BlogPost();

    viewModel.BlogPost.ShortBody = "<p>Something short and sweet to describe the post</p>";
    viewModel.BlogPost.Body = "<p>Enter something blog worthy here...</p>";

    viewModel.Tags = new SelectList(_blogRepo.BlogTags(), "Id", "Name");
    viewModel.Categories = new SelectList(_blogRepo.BlogCategories(), "Id", "Name");

    return View(viewModel);
}

这是视图中的 HTML:

<div class="row">
    <div class="form-group">
        @Html.LabelFor(m => m.BlogPost.Tags, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
        @Html.ListBoxFor(m => m.SelectedTags, Model.Tags, new { @class = "form-control chosen-select", @data_placeholder = "Start typing to see a list of tags" })
        </div>
    </div>
</div>

<div class="row">
    <!-- Button trigger modal -->
    <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#tagModal">
            Add Tag
    </button>
</div>

这是我对模态窗口的部分视图:

@using (Html.BeginForm("SaveTag", "Home", FormMethod.Post, new { id = "tag-form" }))
{
    @Html.AntiForgeryToken()

    <!-- Modal -->
    <div class="modal fade" id="tagModal" tabindex="-1" role="dialog" aria-labelledby="tagModalLabel">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                    <h4 class="modal-title" id="tagModalLabel">Enter a name for a new tag</h4>
                </div>
                <div class="modal-body">
                    <input type="text" id="Name" placeholder="Enter a new tag name" />
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                    <button type="submit" class="btn btn-primary">Save changes</button>
                </div>
            </div>
        </div>
    </div>

}

是否可以在客户端添加标签,将其持久化到数据库中,然后将其添加到我的标签选择列表中而不刷新页面?

PS:仅供参考,我正在使用来自here 的选择多选。

@section scripts {
    <script type="text/javascript" src="~/Scripts/chosen.jquery.min.js"></script>
    <script type="text/javascript">
        $(".chosen-select").chosen()
    </script>
}

编辑:我已经用所有使视图为用户提供模式窗口以输入新标签名称的代码更新了问题。我只是不确定如何在不离开页面的情况下发布,所以我猜测需要某种 Ajax 发布。然后如何处理从该帖子返回的数据。然后如何将新的持久记录添加到选择列表中?

我知道标签没有传递给控制器​​方法,因为它没有绑定到任何类型的模型,但是当我在父视图上使用视图模型时,我不确定我将如何处理它要么。

【问题讨论】:

    标签: asp.net asp.net-mvc twitter-bootstrap asp.net-mvc-5 jquery-chosen


    【解决方案1】:

    为了在视图中动态添加新的BlogTag,您需要使用ajax 将新标签Name 发布到保存BlogTag 并返回其新ID 值的控制器方法。您的控制器方法类似于

    [HttpPost]
    public JsonResult CreateTag(string name)
    {
      BlogTag tag = new BlogTag(){ Name = name };
      db.BlogTags.Add(tag);
      db.SaveChanges();
      return Json(tag.ID);
      // If the above code could result in an error/exception, catch it and return
      // return Json(null);
    }
    

    然后在视图中,处理对话框提交按钮以发布值并更新标签列表

    var url = '@Url.Action("CreateTag")';
    var tagList = $('#SelectedTags');
    $('#tag-form').submit(function() {
      var tagName = $('#Name').val();
      $.post(url, { name: tagName }, function(id) {
        if (id) {
          // add the new tag to the list box
          tagList.append($('<option></option>').val(id).text($('#Name').val()));
          // trigger the chosen update
          tagList.trigger("chosen:updated");  
        } else {
          // Oops - display an error message?
        }
      }).fail(function (result) {
        // Oops - display an error message?
      });
      return false; // cancel the default submit
    });
    

    旁注:我建议您为BlogTagVM 创建一个视图模型(包含带有验证属性的Name 的属性)和一个生成对话框html 的关联部分视图(比如_AddBlogTag.cshtml),所以在主视图中,您可以使用@Html.Partial("_AddBlogTag", new BlogTagVM()),这将允许您使用强类型的 html 帮助程序,并包括客户端验证。

    另请注意,嵌套的&lt;form&gt; 元素是无效的 html,因此请确保对话框的 html 位于视图的主要 &lt;form&gt; 标记之外。

    【讨论】:

    • 我可以看到它是如何工作并实现它的。我可以看到使用 Firefox 开发人员工具将新选项添加​​到 html 源代码中的选项列表中(看起来我比我最初想象的更接近解决方案)。但是,在页面刷新之前,choice-select ui 元素似乎无法识别它。所以澄清一下 - 它附加了html源&lt;option&gt;列表,但没有显示在chosen-select.
    • 取消,我阅读了选择的网站,您可以在tagList.append($('&lt;option&gt;&lt;/option&gt;').val(ID).text(tagName.val())); 之后触发更改/更新事件$("#SelectedTags").trigger("chosen:updated"); 如果您能详细说明我将如何处理无法持久化在数据库中标记我也很乐意+1!干杯。
    • 我的回答中已经有tagList.trigger("chosen:updated");这行:)。有几种方法可以处理失败 - 您可以 return Json(null) 并在脚本中检查 if (id) { // add option } else { // oops } 或者您可以返回一个指示错误的 HttpStatusCodeResult 然后将 .fail(function (result) { // oops }); 添加到 $.post 函数中 - 我已经更新了举例回答
    • 非常感谢。哎呀,所以你很抱歉。虽然我主要阅读 dotnetfiddle,但它并不在那里。现在完美运行。谢谢。
    【解决方案2】:

    我正在做类似的事情,我认为这可能会有所帮助。就我而言,我将值从一个列表“移动”到另一个列表(从“可用”到“使用”),然后保存“使用”列表的值。无论如何,在控制器中,“使用”列表显示为字符串数组。这是我的代码:

           public ActionResult PinchHit(FormCollection form, LineupViewModel lvm, String[] UsedPlayers)
            {
    [Snip]
                if (ModelState.IsValid && lineupResults.IsValid)
                {
    [Snip]
                    foreach (String usedID in UsedPlayers)
                    {
                       gameState.HomeUsedPlayersIDs.Add(Convert.ToInt32(usedID));
                    }
                    uow.Repository<GameState>().Update(gameState);
                    uow.SaveChanges();
                    return RedirectToAction("Index", "GameSummary");
                }
    [Snip]
                return View(lvm2);
            }
    

    希望对您有所帮助。

    根据我的评论:

    这是我用来从数据库中检索数据而不重新加载页面的 AJAX 回调机制,您可以使用它来将数据保存到数据库中。

       <script type="text/javascript">
            function getPositions(id, control) {
                $.ajax({
                    url: "@Url.Action("GetPositions", "Lineup")",
                    data:
                    {
                        id: id
                    },
                    dataType: "json",
                    type: "POST",
                    error: function () {
                        alert("An error occurred.");
                    },
                    success: function (data) {
                        $(control).html("");
                        $.each(data, function (i, item) {
                            $(control).append("<option value=\"" + item.Value + "\">" + item.Text + "</option>");
                        }
                        );
                    }
                });
            }
    </script>
    

    然后在控制器中:

       [HttpPost]
        public ActionResult GetPositions(int id)
        {
            Player player = uow.Repository<Player>().GetById(id);
            if (player == null)
            {
                return (null);
            }
            List<SelectListItem> positionList = new SelectList(player.Positions, "ID", "ShortName").ToList();
            return Json(positionList);
        }
    

    真的很标准。

    【讨论】:

    • 谢谢,但我认为这会导致页面加载,对吗?如果可能的话,我会尽量避免这种情况。我知道我可以发布一个表单,并使用预先输入的字段重新加载视图并更新选择列表,但我希望在客户端进行。
    • 我正在做的是在客户端收集所有值,然后在发布期间将它们持久化(当用户完成所有更改并单击提交按钮时。)你问的是每次添加标签而不重新加载页面时,更改是否会保留?在这种情况下,您需要对 JSON 方法进行 AJAX 回调。我会编辑我的答案。
    • 谢谢,但作为一个完整的初学者,尤其是 JS,没有足够的信息让我到达我认为需要的地方。我有一个带有打开表单的模态窗口,但我的表单数据没有传递到我的控制器,我不确定一旦新标签持久化如何处理它。 (我以为我以前比实际更接近!)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多