Удаленная функция и проверка раскрывающегося списка для не работы в модальном всплывающем окне - PullRequest
0 голосов
/ 07 мая 2020

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

код для модального показа:

<a class="btn btn-sm btn-success btn-flat" onclick="showModal('@Url.Action("CreateOrEditProduct", "Purchases", new { pid=Model.Id, pn=Model.PurchaseNumber },
                                                                                                          Context.Request.Scheme)', 'Add Product', '#productForm')"><i class="fas fa-plus"></i> Add Product</a>

Код в контроллере:

public async Task<IActionResult> CreateOrEditProduct(int id = 0, int pid = 0, string pn = "")
    {
        PurchaseDetailViewModel vmodel = new PurchaseDetailViewModel();
        if (id == 0)
        {
            /*create view code here*/
        }
        else
        {
            /*edit view code here*/
        }

        vmodel.Products = ProductList();
        vmodel.Suppliers = SupplierList();

        return View(vmodel);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> CreateOrEditProduct(int id, PurchaseDetailViewModel purchaseDetail)
    {
        purchaseDetail.Products = ProductList();
        purchaseDetail.Suppliers = SupplierList();
        if (ModelState.IsValid)
        {
            var vmodel = _mapper.Map<PurchaseDetail>(purchaseDetail);
            if (id == 0)
            {
                /*create code here*/
            }
            else
            {
                /*edit code here*/
            }

            return Json(new { isValid = true, html = this.RenderViewAsync("Details", purchaseDetail) });
        }
        return Json(new
        {
            isValid = false,
            html = this.RenderViewAsync("CreateOrEditProduct", purchaseDetail)
        });
    }

код для формы:

    <form id="productForm" asp-action="CreateOrEditProduct" onsubmit="return jQueryAjaxPost(this);" autocomplete="off">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>

    @Html.HiddenFor(Model => Model.PurchaseId)
    @Html.HiddenFor(Model => Model.PurchaseNumber)

    <div class="form-group">
        <label asp-for="ProductId" class="control-label"></label>
        @Html.DropDownListFor(x => Model.ProductId, Model.Products, "**Please select**",
        htmlAttributes: new { @class = "form-control", @id = "Product" })
        @Html.ValidationMessageFor(Model => Model.ProductId, "", new { @class = "text-danger" })
    </div>

    /*some other inputs here*/

    <div class="form-group">
        <button type="submit" class="btn btn-success btn-flat"><i class="far fa-check-circle"></i> Save</button>
        <a class="btn btn-danger btn-flat" asp-controller="Purchases" asp-action="Details" asp-route-id="@Model.PurchaseId"><i class="far fa-times-circle"></i> Cancel</a>
    </div>
</form>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}

Ajax Показать форма и почтовый индекс здесь:

    showModal = (url, title, formid) => {
    $.ajax({
        type: 'GET',
        url: url,
        success: function (res) {
            //$.validator.unobtrusive.parse(formid);
            $('#form-modal .modal-body').html(res);
            $('#form-modal .modal-title').html(title);
            $('#form-modal').modal('show');
        }
    })
}

jQueryAjaxPost = form => {
    try {
        $.ajax({
            type: 'POST',
            url: form.action,
            data: new FormData(form),
            contentType: false,
            processData: false,
            success: function (res) {
                console.log(res);
                if (res.isValid) {
                    //$('#view-all').html(res.html)
                    $('#form-modal .modal-body').html('');
                    $('#form-modal .modal-title').html('');
                    $('#form-modal').modal('hide');
                }
                else
                    $('#form-modal .modal-body').html(res.html.result);
            },
            error: function (err) {
                console.log(err)
            }
        })
        //to prevent default form submit event
        return false;
    } catch (ex) {
        console.log(ex)
    }
}

Раскрывающийся список для кода:

private IList<SelectListItem> ProductList()
    {
        var list = _context.Product.Select(x => new SelectListItem { Text = x.ProductName, Value = x.Id.ToString() }).ToList();
        return list;
    }

Расширение контроллера:

public static class ControllerExtensions
{
    public static async Task<string> RenderViewAsync<TModel>(this Controller controller, string viewName, TModel model, bool partial = false)
    {
        if (string.IsNullOrEmpty(viewName))
        {
            viewName = controller.ControllerContext.ActionDescriptor.ActionName;
        }

        controller.ViewData.Model = model;

        using (var writer = new StringWriter())
        {
            IViewEngine viewEngine = controller.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
            ViewEngineResult viewResult = viewEngine.FindView(controller.ControllerContext, viewName, !partial);

            if (viewResult.Success == false)
            {
                return $"A view with the name {viewName} could not be found";
            }

            ViewContext viewContext = new ViewContext(
                controller.ControllerContext,
                viewResult.View,
                controller.ViewData,
                controller.TempData,
                writer,
                new HtmlHelperOptions()
            );

            await viewResult.View.RenderAsync(viewContext);

            return writer.GetStringBuilder().ToString();
        }
    }
}

Просмотрите код модели и уже убедитесь, что удаленная функция работает без модального

 public class PurchaseDetailViewModel
    {
        public int Id { get; set; }

        [Display(Name ="Product"), Required]
        [Remote("CheckPurchaseProduct", "Purchases", AdditionalFields = "PurchaseId", ErrorMessage = "Product already exists.")]
        public int ProductId { get; set; }

        public IList<SelectListItem> Products { get; set; }

/*other fields here*/
}

Пример вывода без модального:

Вывод без модального

Пример вывода с модальным окном:

Вывод в модальном режиме

Я искал несколько часов, но не могу исправить проблему

1 Ответ

0 голосов
/ 08 мая 2020

Кажется, что ваш модальный экран в вашем представлении бритвы не использует Layout. Если это так, вы не можете использовать @section Script{} в этом представлении бритвы.

Вот моя простая демонстрация, которую вы можете проверить:

1.Index.cs html:

@model PurchaseDetailViewModel
<a class="btn btn-sm btn-success btn-flat" onclick="showModal('@Url.Action("CreateOrEditProduct", "Home", new { pid=Model.Id, pn=Model.PurchaseNumber })')">open</a>
<div class="modal fade" id="form-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close" onclick="Close()">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body" id="details">

            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal" onclick="Close()">Close</button>
                <button type="button" class="btn btn-primary">Save changes</button>
            </div>
        </div>
    </div>
</div>
@section Scripts {
<script>
    showModal = (url, title, formid) => {
        $.ajax({
            type: 'GET',
            url: url,
            success: function (res) {
                $('#form-modal .modal-body').html(res);
                $('#form-modal').modal('show');
            }
        })
    }

    jQueryAjaxPost = form => {
        try {
               //...
            })
            //to prevent default form submit event
            return false;
        } catch (ex) {
            console.log(ex)
        }
    }
</script>
}

2.CreateOrEditProduct.cs html:

@model PurchaseDetailViewModel
@{
       Layout = null;
}
<form id="productForm" asp-action="CreateOrEditProduct" onsubmit="return jQueryAjaxPost(this);" autocomplete="off">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>

    @Html.HiddenFor(Model => Model.PurchaseId)
    @Html.HiddenFor(Model => Model.PurchaseNumber)

    <div class="form-group">
        <label asp-for="ProductId" class="control-label"></label>
        @Html.DropDownListFor(x => Model.ProductId, Model.Products, "**Please select**",
     htmlAttributes: new { @class = "form-control", @id = "Product" })
        @Html.ValidationMessageFor(Model => Model.ProductId, "", new { @class = "text-danger" })
    </div>
    <div class="form-group">
        <button type="submit" class="btn btn-success btn-flat"><i class="far fa-check-circle"></i> Save</button>
        <a class="btn btn-danger btn-flat" asp-controller="Purchases" asp-action="Details" asp-route-id="@Model.PurchaseId"><i class="far fa-times-circle"></i> Cancel</a>
    </div>
</form>

@{
     await Html.RenderPartialAsync("_ValidationScriptsPartial");
}

3.Контроллер:

public class HomeController : Controller
{
    private IList<SelectListItem> ProductList()
    {
        var data = new List<dynamic> {
            new { ProductName ="aaa", Id =1},
            new { ProductName ="bbb", Id =2},
            new { ProductName ="ccc", Id =3}
        };
        var list = data.Select(x => new SelectListItem { Text = x.ProductName, Value = x.Id.ToString() }).ToList();
        return list;
    }
    public IActionResult Index()
    {
        var model = new PurchaseDetailViewModel()
        {
            Id = 1,
            PurchaseNumber = 1001
        };
        return View(model);
    }

    public async Task<IActionResult> CreateOrEditProduct(int id = 0, int pid = 0, string pn = "")
    {
        PurchaseDetailViewModel vmodel = new PurchaseDetailViewModel();
        if (id == 0)
        {
            /*create view code here*/
        }
        else
        {
            /*edit view code here*/
        }

        vmodel.Products = ProductList();

        return View(vmodel);
    }

    [AcceptVerbs("GET", "POST")]
    public IActionResult CheckPurchaseProduct()
    {
        return Json(false);
    }
}

4. Результат:

enter image description here

...