Выполните ненавязчивую проверку формы JQuery без отправки формы

0

У меня есть форма, представляющая элемент. Форма содержит кнопку отправки. Если нажать кнопку "Отправить", необходимо провести проверку ненавязчивой проверки в этих полях.

Если проверка не удалась, больше ничего не должно произойти.

Если проверка прошла, элемент должен быть добавлен в коллекцию Knockout.js observArray.

В обоих случаях весь процесс должен оставаться на стороне клиента без отправки на сервер. Подчинение и проверка на стороне сервера будут проходить на более позднем этапе процесса.

Как я могу достичь желаемого эффекта?

Я использую ASP.Net MVC с аннотациями данных. Я предпочитаю не дублировать логику проверки вручную на стороне клиента.

Я должен также упомянуть, что у меня есть несколько форм на одной странице.

Вот что я сделал так далеко...

Вот мой макет ASP.Net MVC:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - JC Guns Online</title>


    @*---------- Stylesheets ----------*@

    @Styles.Render("~/Content/Bootstrap/bootstrap-theme.css")
    @Styles.Render("~/Content/MightyIT/bootstrap_customizations.css")
    @Styles.Render("~/Content/site.css")
    @Styles.Render("~/Content/MightyIT/custom_styles.css")
    @Styles.Render("~/Content/MightyIT/callout.css") 
    @Styles.Render("~/Content/font-awesome-4.0.3/css/font-awesome.min.css")
    @RenderSection("css", required: false)


</head>
<body>

    <div class="navbar navbar-default navbar-fixed-top">
        <div class="container">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
        </div>
        <div class="navbar-collapse collapse">
            <ul class="nav navbar-nav">

                <li>@Html.ActionLink("Home", "Index", "Home")</li>
                <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                @*<li>
                    @using (Html.BeginForm())
                    {
                        <input id="txtQuickSearch" type="text" class="form-control col-lg-8" placeholder="Search">
                        <img src="~/Content/img/search_32.png" />
                    }
                </li>*@
            </ul>
            @Html.Partial("_LoginPartial")
        </div>
    </div>
    <div class="container body-content">
        <br />
        @RenderBody()

        <br /><br />
        <nav class="navbar navbar-default navbar-fixed-bottom">
            <div style="text-align:center">
                <img src="~/Content/img/logo_small.png" class="img-responsive" />
                <sub style="position:absolute; right:10px; bottom:10px;">&copy; @DateTime.Now.Year </sub>
            </div>
        </nav>
    </div>

    @*---------- Javascripts ----------*@

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/modernizr")
    @Scripts.Render("~/bundles/bootstrap")
    @Scripts.Render("~/Scripts/KnockOut/knockout-3.0.0.js")
    @Scripts.Render("~/Scripts/JQuery/jquery.unobtrusive-ajax.js")
    @Scripts.Render("~/Scripts/JQuery/jquery.validate.js")
    @Scripts.Render("~/Scripts/JQuery/jquery.validate.unobtrusive.js")
    @Scripts.Render("~/Scripts/JQuery/jquery.callout.unobtrusive.js")   
    @Scripts.Render("~/Scripts/MVCFoolProof/mvcfoolproof.unobtrusive.js")    
    @RenderSection("scripts",false)
</body>
</html>

Вот код для соответствующего частичного, над которым я сейчас работаю (есть пара подобных партикулов, которые будут размещены на одной странице):

<form id="AddCrimeForm">
    <div class="panel panel-success">
        <div class="panel-heading">
            <div class="form-horizontal">
                <div class="row">
                    <div class="col-lg-11">Add a crime incident to the list</div>
                    <div class="col-lg-1">
                        <button type="submit" class="btn btn-success btn-xs" onclick="addCrime();"><i class="fa fa-plus"></i> Add</button>
                    </div>
                </div>
            </div>
        </div>

        <div class="panel-body">
            <div class="form-horizontal">
                <div class="row">
                    <div class="col-lg-6">
                        <input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." id="Id" name="Id" type="hidden" value="">
                        <div class="form-group">
                            <label class="control-label col-md-4" for="CaseNumber">Case Number</label>
                            <div class="col-md-8">
                                <input class="form-control text-box single-line" data-val="true" data-val-required="The Case Number field is required." id="CaseNumber" name="CaseNumber" type="text" value="">
                                <span class="field-validation-valid" data-valmsg-for="CaseNumber" data-valmsg-replace="true"></span>
                            </div>
                        </div>
                        <div class="form-group">
                            <label class="control-label col-md-4" for="DateOfIncident">Date Of Incident</label>
                            <div class="col-md-8">
                                <input class="form-control text-box single-line valid" data-val="true" data-val-required="The Date of Incident field is required." id="DateOfIncident" name="DateOfIncident" type="date" value="">
                                <span class="field-validation-valid" data-valmsg-for="DateOfIncident" data-valmsg-replace="true"></span>
                            </div>
                        </div>
                    </div>
                    <div class="col-lg-6">
                        <div class="form-group">
                            <label class="control-label col-md-4" for="Description">Description</label>
                            <div class="col-md-8">
                                <textarea class="form-control text-box multi-line" data-val="true" data-val-required="The Description field is required." id="Description" name="Description"></textarea>
                                <span class="field-validation-valid" data-valmsg-for="Description" data-valmsg-replace="true"></span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</form>

<table class="table table-striped table-hover " id="CrimeList">
    <thead>
        <tr>
            <th>Case Number</th>
            <th>Date of Incident</th>
            <th>Description</th>
            <th></th>
        </tr>
    </thead>
    <tbody data-bind="foreach: items">
        <tr>
            <td data-bind="text: $data.CaseNumber">Column content</td>
            <td data-bind="text: $data.DateOfIncident">Column content</td>
            <td data-bind="text: $data.Description" style="text-wrap: normal">Column content</td>
            @*<td></td>
                <td></td>
                <td></td>*@
            <td>...</td>
        </tr>
    </tbody>
</table>

И вот код для client_crime_kjs.js, со всем моим модемным кодом KnouckoutJS:

$(document).ready(
    function ()
    {

        var Crime = function(CaseNumber, DateOfIncident, Description)
        {
            this.CaseNumber = CaseNumber;
            this.DateOfIncident = DateOfIncident;
            this.Description = Description;
        }

        var initialData = new Array();

        var crimes = function (items)
        {
            var self = this;
            //Data
            self.items = ko.observableArray(items)

            //operations
            self.addCrime = function()
            {
                if ($("#AddCrimeForm").valid()) {
                    self.crime = new Crime($("#CaseNumber").val(), $("#DateOfIncident").val(), $("#Description").val());
                    //var JSONObj = { CaseNumber: $("#CaseNumber").val(), DateOfIncident: $("#DateOfIncident").val(), Description: $("#Description").val() };
                    self.items.push(this.crime);
                }

                //$("#CaseNumber").val() = "";
                //$("#DateOfIncident").val() = "";
                //$("#Description").val() = "";

            }

        }

        ko.applyBindings(crimes(initialData), $("#CrimeList")[0])
    }
);

В основном то, что происходит на этом этапе, заключается в том, что когда поля недействительны, форма не представляется (правильно), но когда она проверяет, она передает (в отличие от моего требования), и мой KO obsablearray впоследствии сбрасывается.

  • 0
    Можете ли вы показать нам, что вы уже сделали?
  • 0
    Обновлено с кодом согласно вашему запросу. Спасибо, что посмотрели!
Теги:
validation
asp.net-mvc
knockout.js

2 ответа

2
Лучший ответ

Поэтому я получил ответ на вышеупомянутый вопрос. Хитрость заключается в том, чтобы установить кнопку type = "button" вместо "submit".

Итак, для кого-то, кто борется с этим, вот пример того, как заставить его работать...

Ваш нокаут ViewModel:

$(document).ready(
    function () {

        var Crime = function (CaseNumber, DateOfIncident, Description) {
            this.CaseNumber = CaseNumber;
            this.DateOfIncident = DateOfIncident;
            this.Description = Description;
        }

        var crimes = function (items) {
            var self = this;
            //Data
            self.items = ko.observableArray(items)

            //operations
            self.addCrime = function () {
                if ($("#AddCrimeForm").valid()) {
                    self.crime = new Crime($("#CaseNumber").val(), $("#DateOfIncident").val(), $("#Description").val());
                    //var JSONObj = { CaseNumber: $("#CaseNumber").val(), DateOfIncident: $("#DateOfIncident").val(), Description: $("#Description").val() };
                    self.items.push(this.crime);

                    $("#CaseNumber").val("");
                    $("#DateOfIncident").val("");
                    $("#Description").val("");
                }
            }

            self.removeCrime = function (item) {
                self.items().remove(item);
            }

        }

        var initialData = new Array();
        ko.applyBindings(crimes(initialData), $("#CrimeList")[0])
    }
);

И вот соответствующий HTML:

<form id="AddCrimeForm">
    <div class="panel panel-success">
        <div class="panel-heading">
            <div class="form-horizontal">
                <div class="row">
                    <div class="col-lg-11">Add a crime incident to the list</div>
                    <div class="col-lg-1">
                        <button type="button" class="btn btn-success btn-xs" onclick="addCrime();"><i class="fa fa-plus"></i> Add</button>
                    </div>
                </div>
            </div>
        </div>

        <div class="panel-body">
            <div class="form-horizontal">
                <div class="row">
                    <div class="col-lg-6">
                        <input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." id="Id" name="Id" type="hidden" value="">
                        <div class="form-group">
                            <label class="control-label col-md-4" for="CaseNumber">Case Number</label>
                            <div class="col-md-8">
                                <input class="form-control text-box single-line" data-val="true" data-val-required="The Case Number field is required." id="CaseNumber" name="CaseNumber" type="text" value="">
                                <span class="field-validation-valid" data-valmsg-for="CaseNumber" data-valmsg-replace="true"></span>
                            </div>
                        </div>
                        <div class="form-group">
                            <label class="control-label col-md-4" for="DateOfIncident">Date Of Incident</label>
                            <div class="col-md-8">
                                <input class="form-control text-box single-line valid" data-val="true" data-val-required="The Date of Incident field is required." id="DateOfIncident" name="DateOfIncident" type="date" value="">
                                <span class="field-validation-valid" data-valmsg-for="DateOfIncident" data-valmsg-replace="true"></span>
                            </div>
                        </div>
                    </div>
                    <div class="col-lg-6">
                        <div class="form-group">
                            <label class="control-label col-md-4" for="Description">Description</label>
                            <div class="col-md-8">
                                <textarea class="form-control text-box multi-line" data-val="true" data-val-required="The Description field is required." id="Description" name="Description"></textarea>
                                <span class="field-validation-valid" data-valmsg-for="Description" data-valmsg-replace="true"></span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</form>

<table class="table table-striped table-hover " id="CrimeList">
    <thead>
        <tr>
            <th>Case Number</th>
            <th>Date of Incident</th>
            <th>Description</th>
            <th></th>
        </tr>
    </thead>
    <tbody data-bind="foreach: items">
        <tr>
            <td data-bind="text: $data.CaseNumber">Column content</td>
            <td data-bind="text: $data.DateOfIncident">Column content</td>
            <td data-bind="text: $data.Description" style="text-wrap: normal">Column content</td>
            @*<td></td>
                <td></td>
                <td></td>*@
            <td>...</td>
        </tr>
    </tbody>
</table>

Еще раз - обратите внимание, что тип кнопки "Добавить" установлен на "кнопка" и НЕ "отправить".

Надеюсь, это поможет всему, что вы кодируете, заглядывает туда!

1

Я в этот момент пытаюсь сделать что-то подобное.

моя идея при начале была такой же, как у вас, но затем я внес некоторые изменения, потому что сложно выполнить сложную проверку с аннотациями данных. С комплексом я имею в виду, что запись не повторяется на базе данных или пользовательский формат на входе.

Поэтому я пошел на FluentValidation, проблема в том, что плавная проверка не всегда работает в ненавязчивой проверке. Так вот что я делаю сейчас.

надеюсь, что это поможет вам, и если вы найдете что-то, что может быть лучше, дайте мне знать:

моя модель с ее проверкой:

    public class BUCashFlow
{
    public int Id { get; set; }
    [Display(Name = "Concepto")]
    public string Text { get; set; }
    [Display(Name = "Valor")]
    public double Value { get; set; }
    public CashFlowType CashFlowType { get; set; }
    [Display(Name = "Cuenta")]
    public int AccountId { get; set; }
    public string User { get; set; }

    public virtual Account Account { get; set; }
}

public class BuCashFlowVal : AbstractValidator<BUCashFlow>
{
    public BuCashFlowVal()
    {

        RuleFor(p => p.Text)
            .NotEmpty().WithMessage(ValHelper.Messages.Required);
        RuleFor(p => p.Value)
            .NotEmpty().WithMessage(ValHelper.Messages.Required);
        RuleFor(p => p.AccountId)
            .NotEmpty().WithMessage(ValHelper.Messages.Required);
    }
}

Я также использую web api, так что вот мой веб-контроллер api, где я проверяю мою новую модель BUCashFlow

        // POST api/BUCashFlows
    [ResponseType(typeof(BUCashFlow))]
    public IHttpActionResult PostBUCashFlow(BUCashFlow bucashflow)
    {
        ValidationResult ValRes = new BuCashFlowVal().Validate(bucashflow);
        if (!ValRes.IsValid)
        {
            return BadRequest(ValRes.Errors[0].ErrorMessage);
        }
        bucashflow.User = User.Identity.GetUserId();
        bucashflow.CashFlowType=CashFlowType.Purchase;
        db.BuCashFlows.Add(bucashflow);
        db.SaveChanges();

        return CreatedAtRoute("DefaultApi", new { id = bucashflow.Id }, bucashflow);
    }

наконец, чтобы показать мои ошибки в js/ko, я делаю это:

            self.addExpense = function(selector) {
            $.ajax({
                type: 'POST',
                url: '@ViewBag.ApiBUExpenses',
                data: $(selector).serialize()
            }).done(function(o) {
                self.expenses.push(new ExpenseVM(self, o.Id, o.Text, o.Value, o.AccountId));
            }).fail(function (o) {
                $(selector).find('.val').html(  '<div class="alert alert-warning alert-dismissable">' +
                                                    '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' +
                                                    '<strong>Warning!</strong> ' + o.responseJSON.Message +
                                                '</div>');
            });
        };

и мою html-форму, которая была сериализована в этом вызове ajax:

            <form id="new-expense-form" data-bind="submit: addExpense">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
                <h4 class="modal-title" id="myModalLabel">Agregar Nuevo Gasto</h4>
            </div>
            <div class="modal-body">
                <div class="form-group">
                    <label class="control-label">Concepto</label>
                    <input name="Text" type="text" class="form-control" />
                </div>
                <div class="form-group">
                    <label class="control-label">Valor</label>
                    <input name="Value" type="text" class="form-control" />
                </div>
                <div class="form-group">
                    <label class="control-label">Cuenta</label>
                    <i data-bind="visible: isLoadingAccounts" class="fa fa-refresh fa-spin pull-right"></i>
                    <select name="AccountId" class="form-control" data-bind="options: accounts, optionsText: 'name', optionsValue: 'Id', optionsCaption: 'Cuenta'"></select>
                </div>
                <div class="val"></div>
            </div>
            <div class="modal-footer">
                <button class="btn btn-default-pnl btn-circle-m" title="Guardar Gasto">
                    <i class="fa fa-check"></i>
                </button>
            </div>
        </form>

Что вы думаете об этом подходе?

Если FoolProof работает как ожидаемый

спасибо за обмен этой библиотекой, теперь, если это работает, вам просто нужно изменить вызов ajax следующим образом:

self.addExpense = function(selector) {
    $(selector).validate()
    if ($(selector).valid()) {
            $.ajax({
                type: 'POST',
                url: '@ViewBag.ApiBUExpenses',
                data: $(selector).serialize()
            }).done(function(o) {
                self.expenses.push(new ExpenseVM(self, o.Id, o.Text, o.Value, o.AccountId));
            })
    }
};    

Обновить

Я видел вашу библиотеку, и я думаю, что это не работает, если это не так, вы всегда можете дублировать свое действие и использовать KnockoutValidation

  • 0
    Для меня сложность проверок не является проблемой - я использую Foolproof для своих проверок DataAnnotations и для крайних случаев, когда требуется еще более сложная проверка, я просто делаю проверку только на стороне сервера (клиент вполне рад сделать это для меня) это так).
  • 0
    Если я правильно понимаю ваш код, вы не выполняете какую-либо проверку на стороне клиента, а вместо этого отправляете запрос AJAX на сервер для проверки? В моем случае этого было бы недостаточно, поскольку нам необходимо разрабатывать автономные функции (иными словами, пользователь должен иметь возможность перехватывать все данные, даже если соединение находится в автономном режиме, без нарушения проверки). Я ценю усилия, хотя - я считаю, что, если бы не это требование, это бы сработало. Так что +1.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню