I have a view that contains a WebGrid. There is also a section for WebGrid search and filtering that includes a text box and a submit button type.
By calling the index ActionResult, all records are loaded correctly in the grid, and when I enter a text in the text box and click the button, the information is received and filtered properly from the controller and it is loaded in the grid.
But by pushing the search button, all the objects on the page are refreshed, while only the grid should be updated, and the other objects on the page should not be refreshed.
(For example، After pressing the search button, the contents of the textbox (<input type="text" />) are empty and buttons blink.)
For this operation, I used Partial View and Ajax.Beginform in index view.
Which part of the code is missing? Why are all the controls on the page updated?
This is my Controler:
Function Index(strName As String) As ActionResult
If strName = Nothing Then
Return View(db.Brands.ToList())
Else
Return View(db.Brands.Where(Function(x) x.BrandName.Contains(strName)).ToList())
End If
End Function
PartialView:
#ModelType IEnumerable(Of Machinary.Brand)
#Code
Dim wg As New WebGrid(Model, rowsPerPage:=10, canPage:=True, canSort:=True, ajaxUpdateContainerId:="wg1")
Dim rowIndex = ((wg.PageIndex + 1) * wg.RowsPerPage) - (wg.RowsPerPage - 1)
End Code
#wg.GetHtml(tableStyle:="table table-bordered table-hovor", mode:=WebGridPagerModes.All,
htmlAttributes:=New With {.id = "wg1", .class = "Grid"},
firstText:="<<",
lastText:=">>",
footerStyle:="table-pager",
columns:=wg.Columns(
wg.Column("BrandName", Sorter("BrandName", "عنوان", wg)),
wg.Column(header:="عملیات", format:=Function(item) New HtmlString(
Html.ActionLink(" ", "BrandEdit", New With {.id = item.id}, htmlAttributes:=New With {.class = "glyphicon glyphicon-edit btn btn-info btn-sm", .data_toggle = "tooltip", .data_placement = "top", .title = "ویرایش"}).ToString() + " " +
Html.ActionLink(" ", "BrandDelete", New With {.id = item.id}, htmlAttributes:=New With {.class = "glyphicon glyphicon-trash btn btn-danger btn-sm", .data_toggle = "tooltip", .data_placement = "top", .title = "حذف"}).ToString()))))
#functions
Public Shared Function Sorter(columnName As String, columnHeader As String, grid As WebGrid) As String
Return String.Format("{0} {1}", columnHeader, If(grid.SortColumn = columnName, If(grid.SortDirection = SortDirection.Ascending, "▲", "▼"), String.Empty))
End Function
End Functions
Index.Vbhtml (Main View):
#Using (Ajax.BeginForm("Index", "Brand", FormMethod.Post, New AjaxOptions With {
.InsertionMode = InsertionMode.Replace,
.UpdateTargetId = "GridList"}))
End Using
<section Class="panel">
<header Class="panel-heading tab-bg-dark-navy-blue">
<label class="bg-transparent wht-color">برندها</label>
</header>
<div Class="panel-body pull-left">
#Using (Html.BeginForm("Index", "Brand", FormMethod.Post))
#Html.TextBox("strName", Nothing, New With {.class = "form-control", .PlaceHolder = "جستجو"})
#<Button type="submit" value="" style="display: none"></Button>
End Using
</div>
<div id="GridList">
#Html.Partial("PVBrandList")
</div>
</section>
<div Class="pull-left btn-toolbar">
<div Class="btn btn-default">
#Html.ActionLink(" ", "BrandAdd", Nothing, htmlAttributes:=New With {.class = "glyphicon glyphicon-plus btn btn-small", .data_toggle = "tooltip", .data_placement = "top", .title = "اضافه کردن سطر جدید"})
</div>
<div Class="btn btn-default">
#Html.ActionLink(" ", "Index", Nothing, htmlAttributes:=New With {.class = "glyphicon glyphicon-tasks btn btn-small", .data_toggle = "tooltip", .data_placement = "top", .title = "لیست برندها"})
</div>
</div>
<input type="text" />
<script type="text/javascript">
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
</script>
The most obvious problem in your view is the submit button exists inside the form which uses Html.BeginForm() helper:
#Using (Html.BeginForm("Index", "Brand", FormMethod.Post))
#Html.TextBox("strName", Nothing, New With {.class = "form-control", .PlaceHolder = "XXXXX"})
#<Button type="submit" value="" style="display: none"></Button>
End Using
which other form using Ajax.BeginForm() helper still empty:
#Using (Ajax.BeginForm("Index", "Brand", FormMethod.Post, New AjaxOptions With {
.InsertionMode = InsertionMode.Replace,
.UpdateTargetId = "GridList"}))
End Using
This setup causing full postback when submit button click event triggered, and subsequently refresh the whole view instead of table grid (with textbox value cleared).
If you want to use AJAX, make sure that you're using Ajax.BeginForm helper with submit button inside that form:
#Using (Ajax.BeginForm("Index", "Brand", FormMethod.Post, New AjaxOptions With {
.InsertionMode = InsertionMode.Replace,
.UpdateTargetId = "GridList"}))
#Html.TextBox("strName", Nothing, New With {.class = "form-control", .PlaceHolder = "XXXXX"})
<button type="submit" style="display: none">Search</button>
End Using
And put <HttpPost> attribute on the target action which returns PartialView:
<HttpPost()>
Public Function Index(strName As String) As ActionResult
If strName = Nothing Then
Return PartialView(db.Brands.ToList())
Else
Return PartialView(db.Brands.Where(Function(x) x.BrandName.Contains(strName)).ToList())
End If
End Function
Thanks a lot . This problem has been fixed. When I search for something, AJAX works correctly. For example, when I click on the header to sort, the grid is refereed, and it's OK.But when the page is loaded for the first time and I do not search for anything, if I click on the title of the grid columns or paging numbers , then the entire page refreshed.
Please see the contents of the controller after your proposed changes:
Function Index() As ActionResult
Return View(db.Brands.ToList())
End Function
<HttpPost>
Function Index(strName As String) As ActionResult
If strName = Nothing Then
Return PartialView("_PVBrandGrid", db.Brands.ToList())
Else
Return PartialView("_PVBrandGrid", db.Brands.Where(Function(x) x.BrandName.Contains(strName)).ToList())
End If
End Function
The first Function Index() As ActionResult that runs for the first time is likely to cause this problem, What is the offer and the solution?
Thank's
Related
I have an Ajax form which is working properly:
<div class="row">
<div class="col-sm-8 col-sm-offset-2 alert alert-info" id="result"></div>
<div class="col-sm-8 col-sm-offset-2">
<h4>Contact Us</h4>
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "result" }))
{
#Html.LabelFor(a=>a.Email)
#Html.EditorFor(a => a.Email)
#Html.ValidationMessageFor(a => a.Email)
#Html.LabelFor(a=>a.Name)
#Html.EditorFor(a => a.Name)
#Html.ValidationMessageFor(a => a.Name)
#Html.LabelFor(a=>a.Phone)
#Html.EditorFor(a => a.Phone)
#Html.ValidationMessageFor(a => a.Phone)
#Html.LabelFor(a=>a.Message)
#Html.EditorFor(a => a.Message)
#Html.ValidationMessageFor(a => a.Message)
<input type="submit" class="btn btn-primary" value="Send Message" />
}
</div>
However, the results div, which I'd like to be styled as an alert, is always displaying by default. How can I make it display only when it has inner text? Is there something like #if(AjaxResult != null) { <div>...</div> }?
I suspect this can be solved within the View only, but I'm including my Controller code below for completeness:
[HttpPost]
public ActionResult Index(ContactUsViewModel model)
{
var fromAddress = new MailAddress("X", "X");
var toAddress = new MailAddress("X", "X");
string fromPassword = "X";
string subject = "GN Query";
string body = model.Message;
var smtp = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
};
using (var message = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body
})
{
smtp.Send(message);
}
return Content("Your message has been received and we will respond within 24-48 hours.", "text/html");
}
You can create a partial view call _alert with your html:
<div class="col-sm-8 col-sm-offset-2 alert alert-info" id="result">
Your message has been received and we will respond within 24-48 hours.
</div>
and then in your view you can set a container div in which it will be rendered when ajax call completes:
<div id="messageContainer">
</div>
now your action should return that partial view and you can have a boolean in your view to decide either render or not:
#model System.Boolean
#if(Model)
{
<div class="col-sm-8 col-sm-offset-2 alert alert-info" id="result">
Your message has been received and we will respond within 24-48 hours.
</div>
}
your controller action will decide either the operation was successful and show the message or not:
bool isSuccess = true; // your logic to set this flag
............
............
{
smtp.Send(message);
}
return PartialView("_alert.cshtml",isSuccess );
and in main view you will have :
<div id="messageContainer">
</div>
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "messageContainer" }))
Hope it helps.
i want to get the value of textbox for Controller
I used Ajax.ActionLink("Search","Result",new{id="**VALUE**"}, new AjaxOptions{...})
#* This is the Index.cshtml *#
<input id="cityName" type="text" class="form-control" placeholder="Enter a CityName">
#Ajax.ActionLink("Search", "Result", new { id = "I want to get the cityName" }, new AjaxOptions { HttpMethod = "Get", UpdateTargetId = "cityInfo", LoadingElementId = "loading" }, new { #class = "btn btn-default" })
<div id="cityInfo"> #When I click the actionlink , the controller will return a partialview
#Html.Partial("Result", Model)
</div>
#*This is the Result.cshtml*#
<p>
#if (#Model!=null)
{
#Model.cityInfo
}
</p>
this is the index.cshtml ->>
enter image description here
Thanks
public PartialViewResult Result(string cityName)//this is the controller
{
CityModel city = new CityModel(cityName);
city.getInfo();
return PartialView("Index",city);
}
You can write a function like below:
Ajax.ActionLink("Search","Result",new{id="id"}, new AjaxOptions{...}) //set temp value
$(document).ready(function(){
//init value
var value = $('#cityName').val();
var href = $('a').attr('href').replace('id', value);
$('a').attr('href', href);
});
If i click Execute button i m redirecting my action to viewpage(GetSection), in this page the partialview(CoverPage) should render automaticly without any event, all it has navbar and CoverPage is also part of navbar, all navbar values are coming from database, i tried "#Html.RenderPartial("CoverPage")" syntax, but it doesn't work for me,and here is my View page
<table style="width:auto">
#foreach (Test_Section p in Model)
{
<tr>
<td>
<div id="ajaxnav" class="navbar-left">
<ul class="nav nav-pills nav-stacked">
<li class="navigationLink">
#Ajax.ActionLink(p.SectionName, p.Title, new { id = p.StdSectionId },
new AjaxOptions
{
UpdateTargetId = "getHtml",
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET"
}, new { style = "color:black" , #class = "navigationLink" })
</li>
</ul>
</div>
</td>
</tr>
}
<div id="getHtml" class="divhtml"></div>
</table>
and the controller is
public ActionResult GetSections()
{
Test_Section[] section = context.Test_Section.ToArray();
return PartialView(section);
}
so please help me.
From your comments, it looks like you want to load the response of the click event of the first link on the page load.
You can trigger the link click on the document ready event with jquery trigger method.
$(function () {
if ($("a.navigationLink").length) {
$("a.navigationLink").eq(0).trigger( "click" );
}
});
I have a comment section set up on one of my pages. The parent view has a partial view which shows the comments for that ID and gives the option to display another partial view to post a comment. When someone post a comment I want the first partial view within the parent to refresh displaying the new comment.
Currently when you click Post Comment, the AddComment method is called and added to the database. I get an error saying that I am passing the wrong type of model to the view. It seems to be trying to pass the return value to my AddComment partial view instead of injecting it into Partent View Div.
Parent View
#model QIEducationWebApp.Models.Course
#{
ViewBag.Title = "Course Details";
}
<h1 class="page-header">#ViewBag.Title</h1>
Javascript is here
.
.
.
<table class="table">
DETAILS HERE
</table>
<ul id="view-options">
<li>#Html.ActionLink("Back to Courses", "Index", "Course")</li>
</ul>
<input type="button" id="View" class="ShowComment" value="Show Comments"/>
<div id="CommentSection"/>
Partial View to view comments
Javascript is here
.
.
.
<div class="CommentSection">
#foreach (var item in Model)
{
<div class="Comment">
<div class="CommentText">
#Html.DisplayFor(modelItem => item.CommentText)
</div>
<div class="CommentSep">
<span class="Commenter">#Html.DisplayFor(modelItem => item.UserName)</span> - <span class="CommentDate">#Html.DisplayFor(modelItem => item.CommentDate)</span>
</div>
</div>
}
<input type="button" id="Post" class="AddComment" value="Add a Comment"/>
<br />
<br />
</div>
<div id="AddComment" />
<br />
<br />
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount
#Html.PagedListPager(Model, page => Url.Action("ViewComments",
new { courseID = #ViewBag.courseID, page }),
PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(
new PagedListRenderOptions { MaximumPageNumbersToDisplay = 5, DisplayLinkToFirstPage = PagedListDisplayMode.IfNeeded,
DisplayLinkToLastPage = PagedListDisplayMode.IfNeeded },
new AjaxOptions() { HttpMethod = "GET", UpdateTargetId = "CommentSection" }))
Method behind the is partial view
public PartialViewResult ViewComments(int courseID, int? page = 1)
{
ViewBag.courseID = courseID;
var coursecomments = db.CourseComments.Where(cc => cc.CourseID == courseID);
int pageSize = 10;
int pageNumber = (page ?? 1);
return PartialView(coursecomments.OrderByDescending(cc => cc.CommentDate).ToPagedList(pageNumber, pageSize));
}
Partial to Post Comment
Javascript is here
.
.
.
#using (Ajax.BeginForm("AddComment", "CourseComment", new { courseID = #ViewBag.courseID, userName = #User.Identity.Name },
new AjaxOptions { UpdateTargetId = "CommentSection" }))
{
#Html.ValidationSummary(true)
<div class="NewComment">
<div class="editor-field">
#Html.TextAreaFor(model => model.CommentText, new { maxLength = 500 })
#Html.ValidationMessageFor(model => model.CommentText)
</div>
<input type="submit" class="PostComment" value="Post Comment" />
<div id="Counter" class="CommentCounter"/>
</div>
}
Controller method linked to the Post Comment Ajax.BeginForm()
public PartialViewResult AddComment(CourseComment coursecomment, int courseID, String userName)
{
coursecomment.CommentDate = System.DateTime.Now;
coursecomment.CourseID = courseID;
coursecomment.UserName = userName;
if (ModelState.IsValid)
{
db.CourseComments.AddObject(coursecomment);
db.SaveChanges();
}
ViewBag.courseID = courseID;
return ViewComments(courseID);
}
Adding pictures
Details
After selecting View Comments button
After selecting Add Comment
After Posting the the comment I want the list of Comments to refresh displaying the newly added Comment. Like So
For now I have it changed. I wanted to the comments section to be hidden until the show comments was clicked. Then after posting a comment on the comments section was refreshed, but I couldn't get that to work. So just reloading the whole page will refresh the comments section, but make it hidden at that time. I made it so that the comments section shows by default without the option to hide it. So unless anyone can figure out a way to get it to work how I wanted, this works for now.
I'm trying to bring over the IDs of the input elements "submit" and "skip" and do some logic based on which button was pushed. It doesn't appear to be coming over in the Request object. How can I do this???
<div id="modal">
<% using (Ajax.BeginForm("Promo", new AjaxOptions { UpdateTargetId = "modal" }))
{ %>
<div id="modal_inner">
<div style="clear: both;">
<%= Html.TextBox("Data1")%>
<input name="submitBtn" id="submitBtn" type="image" src="button_submit.gif" width="74" alt="Submit" />
<input name="skipBtn" id="skipBtn" type="image" src="button_skip.gif" alt="Skip" />
<br />
</div>
</div>
<% } %>
</div>
public JavaScriptResult Promo(string Data1)
{
string submitBtn = Request.Params["submitBtn"];
string skipBtn = Request.Params["skipBtn"];
if (skipBtn != null)
{
Session["Data1"] = "Default";
return JavaScript("window.top.location.href ='" + Url.Action("Index", "Lead") + "';");
}
if (submitBtn != null && IsValidCode(Data1))
{
Session["Data1"] = Data1;
return JavaScript("window.top.location.href ='" + Url.Action("Index", "Lead") + "';");
}
Session["Data1"] = "Default";
return JavaScript("$('TB_window').dispose(); TB_show('', '#TB_inline?&width=344&height=294&inlineId=modal', '::::');");
}
I had the same problem using jQuery, it would not serialize the name of the form element I clicked. I had to seperately detect the onclick of the submit button, get the name of the button, and add it to the serialized query to be sent back with the Ajax call.
Sorry I do not know which Ajax framework you are using here so I cannot help with the actual code.