[RESOLVED]How to update two different target ids when using Ajax.BeginForm?

How can you replace two different targetids when using Ajax.BeginForm? I have the following form but when there are validation errors eg when user submits form without adding any comments I can only replace targetid "Comments".

@Html.Partial("_CreateComment", Model)

<div id="Comments">
    @* Get list of all comments *@
    @Html.Action("Comments", "Blog")
</div>
// _CreateComment partial view
<div id="CommentForm">

	@Html.ValidationMessageFor(model => model.Comment)

	@using (Ajax.BeginForm("AddComment", "Blog", new AjaxOptions
	{
            HttpMethod = "POST",
            InsertionMode = InsertionMode.Replace,
            UpdateTargetId = "Comments"
         
	} ))
	{
             @Html.ValidationSummary(true)

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

  
	    <div>
		Add Comment: @Html.TextAreaFor(model => model.Comment, 1, 100, new { @Class = "commentbox" })
            </div>

             <div >
                <input type="submit" id="button" value="Add" /> 
            </div>
        }
</div>
// AddComment controller action

[HttpPost]
public ActionResult AddComment(Comment comment)
{

	Blog blog = _repository.GetBlogDetails(comment.BlogID);

        if (ModelState.IsValid)
	{

	   // Add Comment to DB..
           _repository.AddBlogComment(Comment);

     
           // Redirect to action and retrieve all comments 
           return RedirectToAction("Comments", new { id = blog.BlogID });

        }

        if (Request.IsAjaxRequest()) //was this request an AJAX request?
        {
                return PartialView("_CreateComment", blog); 
        }
        else
        {
                return View(blog);
        }
}

Any ideas how to fix. Basically i need to update two targetids – one for when comment is successfully added targetid "Comments" needs to replaced and when there are validation errors targetid "CommentForm" needs to be replaced.

If you want to make the Comments field required, just add the annotation to your Comment class

[Required]
public string Comment { get; set; }

And then add the jquery unobtrusive validation script to the scripts-section of your View:

@section scripts {
  @Scripts.Render("~/bundles/jqueryval")
}

This code will validate your form upon submission.

The comment class already has the required annotation and the validation is working. However when there are error what I want to do is simply redsiplay the form with the error message. What i need is some way to have two targetids so that the correct region
is being replaced.

Can you move the "Comments" div inside the partial control (that is inside the Form). If you do this, then on Ajax.BeginForm you can reload the "CommentForm" based on the output of the post.

On the server if the Model is not valid, you can use ModelState.Add to add the error message and hide the "comments" div. if the model is valid, you can show the "Comments" div

I have moved "Comments" div inside the partial control as follows:

<div id="Comments">

   <div id="CommentForm">

	@Html.ValidationMessageFor(model => model.Comment)

	@using (Ajax.BeginForm("AddComment", "Blog", new AjaxOptions
	{
            HttpMethod = "POST",
            InsertionMode = InsertionMode.Replace,
            UpdateTargetId = "Comments"
         
	} ))
	{
             @Html.ValidationSummary(true)

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

  
	    <div>
		Add Comment: @Html.TextAreaFor(model => model.Comment, 1, 100, new { @Class = "commentbox" })
            </div>

             <div >
                <input type="submit" id="button" value="Add" /> 
            </div>
        }
   </div>

   <div >
    	    @* Get list of all comments *@
    	    @Html.Action("Comments", "Blog")
   </div>

</div>

The form re-displays correctly but no validation errors are showing? One thing I have noticed is when I comment out the Html.Action() as below then the validation errors seem to work but then obviously none of my existing comments are displayed.

 @* Html.Action("Comments", "Blog") *@

The above html.action displays another partial view which has a for loop to display all the comments as follows:

@model IEnumerable<DB.Models.BlogComment>

@foreach (var item in Model)
{

   //...some stuff
}

any idea why its behaving like this.

GStar99

Html.Action("Comments", "OneToOne")

Where have you included this partial view? Is it inside the comments div?

sorry the partial view should be Html.Action("Comments", "Blog"). I have updated the original reply. It is inside the "comments" div as show above.

GStar99

How can you replace two different targetids when using Ajax.BeginForm?

handle onsuccess venet of ajax form.

in handler, update the two target divs. onsuccess handler has the parameter with output

Onsuccess will always be true since the controller action that is called by the ajax.beginform always works even when there are model validation errors – see the above controller code in my earlier post.

If I’ve miss-understood your answer please provide a short example?

you can have only one target id for a ajax form, what it does is, post the request, get back the response, put the html response in the target element. If i understood correctly you want to give the real time comments, even if the current request has errors.
try the following

1) Remove client side validation, remove both jquery unobtrusive and jquery validate. Have only server side validation.

2) In server code refresh the list of comments irrespective of validation hence even if there is error your comments section is refreshed. Add the comments to database only when it is not empty, so that you dont get empty texts

Blog blog = _repository.GetBlogDetails(comment.BlogID);

        if (ModelState.IsValid)
{

   // Add Comment to DB.. _repository.AddBlogComment(Comment);     
          
// Redirect to action and retrieve all comments

           //
return RedirectToAction("Comments",
new { id
= blog.BlogID
});

        }

// refresh the page even though the current user left the comment column empty

return RedirectToAction("Comments",
new { id
= blog.BlogID
});
       
if (Request.IsAjaxRequest())
//was this request an AJAX request?
       
{
               
return PartialView("_CreateComment", blog);

       
}
       
else
       
{
               
return View(blog);
       
}

Leave a Reply