3

I need to make some form using Razor and Devexpress controls. When user opens Devexpress popup control there appear a form with fields he needs to enter. Here is my view:

@model Models.Request
@Html.DevExpress().PopupControl(
settings =>
{
    settings.Name = "newRequest";
    settings.CallbackRouteValues = new { Controller = "Request", Action = "RequestForm" };
    settings.EnableClientSideAPI = true;
    settings.Width = 450;
    settings.ShowHeader = true;
    settings.ShowShadow = true;
    settings.PopupAnimationType = AnimationType.Fade;
    settings.AllowDragging = true;
    settings.Modal = true;
    settings.SetContent( () =>
    {
        using ( Html.BeginForm( ))
        {
            ViewContext.Writer.Write( "<div id = 'products'>" );
            foreach(var product in Model.Products)
            {
                Html.RenderPartial( "ProductPartial", product );
            }
            ViewContext.Writer.Write( "</div>" );

            //Total days field
            @Html.DevExpress().SpinEdit(
                            cSettings =>
                            {
                                cSettings.Name = "numberOfProducts";
                                cSettings.Properties.EnableClientSideAPI = true;
                                cSettings.Width = 125;
                                cSettings.Properties.MinValue = 0;
                                cSettings.Properties.MaxValue = 100;
                                cSettings.ControlStyle.BackColor = System.Drawing.Color.FromArgb( 82, 82, 82 );
                                cSettings.ControlStyle.ForeColor = System.Drawing.Color.White;
                            } ).Bind( Model.NumberOfProducts ).GetHtml();

            //POST BACK
            @Html.DevExpress().Button( saveSett =>
            {
                saveSett.Name = "Save";
                saveSett.Text = "Save";
                saveSett.Width = 40;
                saveSett.Height = 25;
                saveSett.ControlStyle.CssClass = "button";
                saveSett.Styles.EnableDefaultAppearance = false;
                saveSett.EnableClientSideAPI = true;
                saveSett.UseSubmitBehavior = true;
                //saveSett.ClientSideEvents.Click = "function(s, e) { if(CheckValidation(s, e)) {} }";
            } ).GetHtml();
        }
    } );    
} ).GetHtml();

I expected that when my view is being rendered that it will call http get method, but it is not the case, it is always calling post method (if there are get post with same names) defined with this:

settings.CallbackRouteValues = new { Controller = "Request", Action = "RequestForm" };

Why is that so? And if I change post method name (that will be called on submit) it gives me an error, saying that there is no method to be called.

Further more, I have button that I wanted to use for submitting form: settings.CallbackRouteValues = new { Controller = "Request", Action = "RequestForm" }; But it does not even come into any action method in controller. Why is that so?

Here are my action methods:

public ActionResult RequestForm()
{
    //...
}

[HttpPost]
public ActionResult RequestForm([ModelBinder(typeof(DevExpressEditorsBinder))] Request request)
{
    //...
}

How to post back my model? What is the best way to do that? Obviously it is not working with these Devexpress controls in normal way. Can I somehow post back this model with jquery? What is the best way? Please advise.

bambi
  • 1,159
  • 2
  • 14
  • 31

1 Answers1

3

I always use below solution when I want to show popup form with validation. First of all I create popup control generally only with callback route value (optionally use Begin and End callback and other properties):

@Html.DevExpress().PopupControl(settings =>
{
settings.Name = "newRequest";
settings.CallbackRouteValues = new { Controller = "Request", Action = "GetRequestForm" };
//[Optionally]: If you want pass data to action controller or set popup properties
settings.ClientSideEvents.BeginCallback = "myLogic.onBeginActionCallback";     
settings.ClientSideEvents.EndCallback = "myLogic.onEndActionCallback";
}).GetHtml()

Next I create controller actions:

    public ActionResult GetRequestForm()        {
        // … some logic here ...
        return PartialView("_PartialView", viewModel);
    }

    [HttpPost]
    public ActionResult RequestForm([ModelBinder(typeof(MyBinder))] Request request)
    {
        // … some logic here ...
        return Json(new { success = true });
    }

Next I create view (name: "_PartialView"):

@using (Ajax.BeginForm("RequestForm", "Request",
new AjaxOptions
{  HttpMethod = "POST"  }, new { id = "saveForm" }))
{
    @Html.DevExpress().TextBox(settings =>
    {
        settings.Name = "someProperty";
    }).GetHtml()

// … other properties…

@Html.DevExpress().Button(settings =>
{
   settings.Name = "SaveButton";
   settings.Text = "Save"; 
   settings.ClientSideEvents.Click = "function(s,e) { myLogic.saveForm(); }";
   settings.UseSubmitBehavior = false;
 }).GetHtml()
}

And finally I create JS script which use JQuery validation (for example myLogic.js):

var myLogic = function () {

function saveForm(){
var saveForm = $("#saveForm");
    saveForm.removeData('validator');
    saveForm.validate(validationSettings);

// jQuery validation
$("#someProperty_I").rules("add", {
    required: true,
    // Connect with server example
    remote: {
        url: '/Request/CheckValue',
        data: {
            //.. some logic here ..
        }
    },
    messages: {
        required: "Required!",
        remote: "Validation message"
    }
});

// and add other jQuery validation

if (saveForm.valid()) {
        saveForm.submit();
    }
}

var validationSettings = {
    errorPlacement: function (error, element) {
        error.appendTo(element.parent("td").parent("tr").parent("tbody").parent("table").parent("td"));
    }
}

return {
    saveForm: saveForm
}}();

Of course you should include jQuery scripts:

1. jquery.validate.min.js
2. jquery.validate.unobtrusive.min.js