WedX - журнал о программировании и компьютерных науках

Модальное окно MVC 4 и AJAX

Я использую MVC 4 и Entity Framework для разработки веб-приложения. У меня есть таблица, которая содержит людей. Также есть кнопка «Редактировать», которая вызывает модальное окно, и благодаря ей пользователь может редактировать человека. Я использую частичный вид для этого.

Мой вопрос: в моем действии я возвращаю представление, но я просто хочу, чтобы при нажатии кнопки «Сохранить» модальное окно исчезало, а моя таблица обновлялась. Есть идеи?

Действия :

[HttpGet]
public ActionResult EditPerson(long id)
{
    var person = db.Persons.Single(p => p.Id_Person == id);

    ViewBag.Id_ProductPackageCategory = new SelectList(db.ProductPackageCategories, "Id_ProductPackageCategory", "Name", person.Id_ProductPackageCategory);

    return PartialView("_EditPerson", person);
}

[HttpPost]
public ActionResult EditPerson(Person person)
{

    ViewBag.Id_ProductPackageCategory = new SelectList(db.ProductPackageCategories, "Id_ProductPackageCategory", "Name", person.Id_ProductPackageCategory);

    if (ModelState.IsValid)
    {
        ModelStateDictionary errorDictionary = Validator.isValid(person);

        if (errorDictionary.Count > 0)
        {
            ModelState.Merge(errorDictionary);
            return View(person);
        }

        db.Persons.Attach(person);
        db.ObjectStateManager.ChangeObjectState(person, EntityState.Modified);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(person);
}

Частичный вид (фактически, модальное окно):

@model BuSIMaterial.Models.Person

<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h3 id="myModalLabel">Edit</h3>
</div>
<div>

@using (Ajax.BeginForm("EditPerson", "Person", FormMethod.Post,
                    new AjaxOptions
                    {
                        InsertionMode = InsertionMode.Replace,
                        HttpMethod = "POST",
                        UpdateTargetId = "table"
                    }))
{

    @Html.ValidationSummary()
    @Html.AntiForgeryToken()

    @Html.HiddenFor(model => model.Id_Person)

    <div class="modal-body">
       <div class="editor-label">
            First name :
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.FirstName, new { maxlength = 50 })
            @Html.ValidationMessageFor(model => model.FirstName)
        </div>
        <div class="editor-label">
            Last name :
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.LastName, new { maxlength = 50 })
            @Html.ValidationMessageFor(model => model.LastName)
        </div>
        <div class="editor-label">
            National number :
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.NumNat, new { maxlength = 11 })
            @Html.ValidationMessageFor(model => model.NumNat)
        </div>
        <div class="editor-label">
            Start date :
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.StartDate, new { @class = "datepicker", @Value = Model.StartDate.ToString("yyyy/MM/dd") })
            @Html.ValidationMessageFor(model => model.StartDate)
        </div>
        <div class="editor-label">
            End date :
        </div>
        <div class="editor-field">
            @if (Model.EndDate.HasValue)
            {
                @Html.TextBoxFor(model => model.EndDate, new { @class = "datepicker", @Value = Model.EndDate.Value.ToString("yyyy/MM/dd") })
                @Html.ValidationMessageFor(model => model.EndDate)
            }
            else
            {
                @Html.TextBoxFor(model => model.EndDate, new { @class = "datepicker" })
                @Html.ValidationMessageFor(model => model.EndDate)
            }
        </div>
        <div class="editor-label">
            Distance House - Work (km) :
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.HouseToWorkKilometers)
            @Html.ValidationMessageFor(model => model.HouseToWorkKilometers)
        </div>
        <div class="editor-label">
            Category :
        </div>
        <div class="editor-field">
            @Html.DropDownList("Id_ProductPackageCategory", "Choose one ...")
            @Html.ValidationMessageFor(model => model.Id_ProductPackageCategory) <a href="../ProductPackageCategory/Create">
                Add a new category?</a>
        </div>
        <div class="editor-label">
            Upgrade? :
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Upgrade)
            @Html.ValidationMessageFor(model => model.Upgrade)
        </div>
    </div>
    <div class="modal-footer">
        <button class="btn btn-inverse" type="submit">Save</button>
    </div>
}

</div>

И мой скрипт, который вызывает модальное окно:

$(document).ready(function () {

    $('.edit-person').click(function () {
           var id = $(this).data("id");
           var url = '/Person/EditPerson/'+id;
           $.get(url, function(data) {

               $('#edit-person-container').html(data);
               $('#edit-person').modal('show');

           });
    });

});

Ответы:


1

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

Вместо того, чтобы возвращать представление из этого действия контроллера, вы можете вернуть частичное представление, содержащее таблицу. А затем в обратном вызове успеха вызова AJAX просто обновите соответствующий контейнер.

15.04.2013
  • Кажется, я понимаю, что вы пытаетесь объяснить. Но что вы подразумеваете под успешным обратным вызовом AJAX? 15.04.2013
  • В вашем модальном режиме вы отображаете форму AJAX, которая определяется с помощью UpdateTargetId = "table". Я предполагаю, что эта таблица соответствует id="table" вашего контейнера. Это то, что будет обновлено с результатом вашего вызова AJAX. Но обычно это должен быть div-контейнер таблицы, чтобы избежать двойного попадания таблицы в DOM. 15.04.2013
  • Теперь я понимаю. Фактически, в настоящее время я возвращаю представление, содержащее таблицу, но это не частичное представление. Должен ли я преобразовать простое представление индекса в частичное представление? 15.04.2013
  • Нет, вы должны перевести таблицу в частичное представление. А затем пусть ваше представление индекса отобразит это частичное представление. Что касается действия POST, оно должно возвращать то же частичное представление. 15.04.2013

  • 2

    нужно будет внести пару изменений, но вот что я бы сделал в этом случае

    1) изменить метод публикации EditPerson с результата действия на JsonResult

    [HttpPost]
    public JsonResult EditPerson(Person person) 
    {
    
        // code here to save person
    
        bool success = true; // somehow determine if the save was successful
        string msg = ""; // error message is needed?
        return JsonResult(new {success,msg, person});
    }
    

    2) Добавьте функцию javascript, чтобы закрыть модальное окно.

    function closeModal(response){
    
        // the response is the Json Result sent back from the action
    
        if (response.success === true){
            // actually got a true response back
        }
        $('#edit-person').modal('show'); // or similar code
    }
    

    3) Затем обновите вызов Ajax для выполнения кода, когда он будет успешным.

    @using (Ajax.BeginForm("EditPerson", "Person", FormMethod.Post,
                    new AjaxOptions
                    {
                        InsertionMode = InsertionMode.Replace,
                        HttpMethod = "POST",
                        UpdateTargetId = "table",
                        OnSuccess = "closeModal(response);" // or javascript code to close the modal, you can also 
                    }))
    { ...
    

    пара советов

    Мне не нравятся помощники MVC ajax. Я думаю, что они раздуты, и я чувствую, что есть другие фреймворки, которые лучше справляются с этим. Это мое мнение. Хотя каждому свое. Я бы предпочел сам использовать библиотеку jQuery ajax. Я думаю, что его проще использовать, но опять же, решать вам.

    OnSuccess означает, что «Успех сервера» не сохраняет успех. так что будьте осторожны.

    Отказ от ответственности: я написал это, когда устал, поэтому это может быть не на 100%, дайте мне знать о любых проблемах.

    Удачи

    15.04.2013
  • Спасибо за вашу помощь, я попробую и дам вам знать. 15.04.2013

  • 3

    В вашем действии POST вы можете вернуть следующее:

    return Json(new { error = false, message = "Person edited." });
    

    В AjaxOptions в Ajax.BeginForm добавьте следующее:

    OnSuccess = "Modal.onAjaxSuccess"
    

    Затем где-нибудь, скажем, в script.js:

    function onAjaxSuccess(data, status, xhr) {
        if (data.error) {
            $.notify({
                type: "error",
                text: data.message
            });
        }
        else {
            $('.modal').modal('hide');
        }
    }
    

    Это закроет окно, но я все еще не могу убрать затемненный экран, связанный с модальными окнами Bootstrap, он также не будет обновлять DIV с помощью AJAX - может быть, Дарин может пролить свет?


    Если вам все еще интересно, как это сделать, вот как:

    У вас есть действие GET, которое возвращает список людей:

    [HttpGet]
    public ActionResult People()
    {
        return PartialView("_ListOfPeoplePartial");
    }
    

    Затем есть функция JS, которая срабатывает, когда вы нажимаете кнопку «Сохранить» (например, btn-save-new-person) в модальном окне, которое позволяет вам создавать новых людей:

    $(function () {
        $(document.body).on('click', '#btn-save-new-person', function (e) {
            $('#create-new-person-modal').modal('hide');
            $('body').removeClass('modal-open');
            $('.modal-backdrop').remove();
            var url = "/Home/People";
            $.get(url, function (data){
                $('#list-of-people').html(data);
            });
        });
    });
    
    15.04.2013
  • Спасибо, я тоже попробую. 15.04.2013
  • Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]