2

在 HTML 表单中,如何绑定 jquery 控件(例如 tokeninput),就像绑定普通原始类型到模型一样?我正在努力寻找方法来做到这一点,我知道你可以使用自定义模板等,但是 jquery 插件没有任何东西。

具体来说,我使用的是 tokenInput,请参见此处(http://loopj.com/jquery-tokeninput/)。这是我针对标准 HTML 文本输入应用的 jQuery 代码。对于每个按键,它都会转到控制器以返回作者列表。您还可以预填充作者,我使用 HTML5 中的数据标签来预填充控件。

 $("#AUTHORs").tokenInput('/author/getauthors/', {
        hintText: "Enter surname",
        searchingText: "Searching...",
        preventDuplicates: true,
        allowCustomEntry: true,
        highlightDuplicates: false,
        tokenDelimiter: "*",
        resultsLimit: 10,
        theme: "facebook",
        prePopulate: $('#AUTHORs').data('AUTHORs')
    });

我从我的角度发布了一些代码,只是为了向您准确展示我试图绑定到模型的内容。

@model myModels.BOOK

@{
    ViewBag.Title = "Edit";
}

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Basic</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.TITLE)
        </div>
        <div class="editor-field" >
            @Html.EditorFor(model => model.TITLE)
            @Html.ValidationMessageFor(model => model.TITLE)
        </div>
    <div class="authors">
            <div class="editor-field">
                <input type="text" id="authors" name="authors" data-val="true"  data-val-required="You must enter at least one author" data-authors="@Json.Encode(Model.AUTHORs.Select(a => new { id = a.AUTHOR_ID, name = a.FULL_NAME }))"/>
                <span class="field-validation-valid" data-valmsg-for="authors" data-valmsg-replace="true"></span>
            </div>
        </div>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

这是我在表单上尝试更新模型(按“保存”后)时使用的代码:

  [HttpPost]
        public ActionResult Edit(BOOK book)
        {
             if (ModelState.IsValid)
            {
                db.Entry(book).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Details", new { id = book.REF_ID });
            }
            ViewBag.REF_ID = new SelectList(db.REFERENCEs, "REF_ID", "REF_ID", book.REF_ID);
            return View(book);
        }

当您查看 HTML 中的代码时,它已经从 tokeninput 元素中格式化了作者,看起来像这样,而且我认为这种格式似乎有一个真正的问题:

<input type="text" id="AUTHORs" name="AUTHORs" data-val="true" data-val-required="You must enter at least one author" data-authors="

[{&quot;id&quot;:156787,&quot;name&quot;:&quot;Faure,M.&quot;},

{&quot;id&quot;:177433,&quot;name&quot;:&quot;Wang,D.Z.&quot;},

{&quot;id&quot;:177434,&quot;name&quot;:&quot;Shu,L.Sh&quot;},

{&quot;id&quot;:177435,&quot;name&quot;:&quot;Sheng,W.Z.&quot;}]"

style="display: none; ">
4

4 回答 4

4

看来您正在使用tokeninput 插件。让我们通过一个分步示例来说明如何使用 ASP.NET MVC 实现这一点:

模型:

public class Book
{
    public string Title { get; set; }
    public IEnumerable<Author> Authors { get; set; }
}

public class Author
{
    public int Id { get; set; }
    public string Name { get; set; }
}

控制器:

public class HomeController : Controller
{
    // fake a database. Obviously that in your actual application
    // this information will be coming from a database or something
    public readonly static Dictionary<int, string> Authors = new Dictionary<int, string>
    {
        { 1, "foo" },
        { 2, "bar" },
        { 3, "baz" },
        { 4, "bazinga" },
    };

    public ActionResult Index()
    {
        // preinitialize the model with some values => obviously in your
        // real application those will be coming from a database or something
        var model = new Book
        {
            Title = "some title",
            Authors = new[] 
            {
                new Author { Id = 2, Name = "bar" }
            }
        };
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(Book book)
    {
        return Content(string.Format("thanks for selecting authors: {0}", string.Join(" ", book.Authors.Select(x => x.Name))));
    }

    public ActionResult GetAuthors(string q)
    {
        var authors = Authors.Select(x => new
        {
            id = x.Key,
            name = x.Value
        });
        return Json(authors, JsonRequestBehavior.AllowGet);
    }
}

看法:

@model Book
@using (Html.BeginForm())
{
    <div>
        @Html.LabelFor(x => x.Title)
        @Html.EditorFor(x => x.Title)
    </div>
    <div>
        @Html.TextBoxFor(
            x => x.Authors, 
            new { 
                id = "authors", 
                data_url = Url.Action("GetAuthors", "Home"), 
                data_authors = Json.Encode(
                    Model.Authors.Select(
                        x => new { id = x.Id, name = x.Name }
                    )
                ) 
            }
        )
    </div>
    <button type="submit">OK</button>
}

<script type="text/javascript" src="@Url.Content("~/scripts/jquery.tokeninput.js")"></script>
<script type="text/javascript">
    var authors = $('#authors');
    authors.tokenInput(authors.data('url'), {
        hintText: 'Enter surname',
        searchingText: 'Searching...',
        preventDuplicates: true,
        allowCustomEntry: true,
        highlightDuplicates: false,
        tokenDelimiter: '*',
        resultsLimit: 10,
        theme: 'facebook',
        prePopulate: authors.data('authors')
    });
</script>

最后一步是编写一个自定义模型绑定器,它将从 id 中检索作者:

public class AuthorModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var values = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (values != null)
        {
            // We have specified asterisk (*) as a token delimiter. So
            // the ids will be separated by *. For example "2*3*5"
            var ids = values.AttemptedValue.Split('*').Select(int.Parse);

            // Now that we have the selected ids we could fetch the corresponding
            // authors from our datasource
            var authors = HomeController.Authors.Where(x => ids.Contains(x.Key)).Select(x => new Author
            {
                Id = x.Key,
                Name = x.Value
            }).ToList();
            return authors;
        }
        return Enumerable.Empty<Author>();
    }
}

将在 Application_Start 中注册:

ModelBinders.Binders.Add(typeof(IEnumerable<Author>), new AuthorModelBinder());
于 2012-09-24T10:57:52.517 回答
0

我做了一个小测试-似乎这种属性文本不是错误,并且浏览器将其识别为 JSON 对象是正确的

尝试 $("#authorlist").data("authors")在浏览器中添加要观看的表达式(按 F12)或在控制台中执行它 - 对我来说,它返回有效的 javascript 对象。

于 2012-09-24T11:06:16.433 回答
0

data-authors="@Json.Encode(Model.AUTHORs.Select(a => new { id = a.AUTHOR_ID, name = a.FULL_NAME }))"

我认为这应该是:

data-authors="@Html.Raw(Json.Encode(Model.AUTHORs.Select(a => new { id = a.AUTHOR_ID, name = a.FULL_NAME })))"
于 2012-09-24T10:54:19.273 回答
0

您可以使用序列化

$("form").on('submit', function(event){
    event.preventDefault();
    var form = $(this);

    $.ajax({
       url: form.attr('action'),
       type: form.attr('method'),
       data: form.serialize(),
       success: function(r) { }
    });
});
于 2012-09-20T10:39:45.897 回答