I'm having trouble with a new MVC4 site I'm working on. I can't seem to get the javascript to run at all. It doesn't throw an error, it just does nothing.
What am I missing?
Here's my page code:
#model IEnumerable<WiseGalleriesEntities.Medium>
#{
ViewBag.Title = "ManageMedium";
}
<div class="title">
<h1>Mediums...</h1>
</div>
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#using (Ajax.BeginForm("Create", "Medium", new AjaxOptions() { UpdateTargetId = "MediumListDiv" }, new { id = "frmAddMedium" }))
{
<div class="span12">
<div>
<div class="editor-field">
#Html.TextBox("txtDescription")
</div>
</div>
Add Medium
</div>
}
<div id="MediumListDiv">
#Html.Partial("Medium.List", Model)
</div>
Instead of using the href attribute, use the onclick attribute.
<a onclick="$('#frmAddMedium').submit();" class="btn-primary btn-small">Add Medium</a>
Related
I have a view that updates a partial view on a get request but when I try to add eventlisteners using vanilla JS and this.form.submit() it's submitting as a post request which is reloading the page and returning just the partial view instead of an ajax request.
Here's my code:
<body style="overflow-x:hidden !important;">
<h6>Activity Management</h6>
#using (Ajax.BeginForm("getActivityManagementTwoActivities", "CallCenter", new AjaxOptions{HttpMethod= "Get", UpdateTargetId= "activitiesForPartial"}))
{
<div class="row ">
<div class="col-md-12" style="float:right;">
<div class="dateWrapper">#{ Html.RenderPartial("_DateFilter"); } </div>
</div>
</div>
<div class="row" style="margin-top: 10px; margin-bottom: 8px;">
<div class="col-md-3 ActivityManagementTwoHeader" style="font-size:12px; font-weight: bold">
Displaying Results 5 of 5
</div>
<div class="col-md-3">
Items per page:
#Html.DropDownList("results", new List<SelectListItem>
{
new SelectListItem { Value = "25", Text= "25"},
new SelectListItem { Value = "50", Text= "50"},
new SelectListItem { Value = "100", Text= "100"},
})
<button type="submit" value="Submit">Submit</button>
</div>
<div class="col-md-3">
<select id="test2222">
<option>Filter</option>
<option>test</option>
</select>
<select>
<option>Sort</option>
</select>
</div>
</div>
}
<div id="activitiesForPartial">
#{ Html.RenderPartial("_ActivityManagementCollapseComponent", Model);}
</div>
<script>
//this part is failing to update as an AJAX
document.getElementById("test2222").addEventListener("change", function () {
alert("test");
this.form.submit();
})
</script>
The problem is the request is being sent as a POST which just wants to reload the page and only return a partial view. I just want to update the partial view AJAXingly without reloading the page.
My button works. The Submit works just fine.
I am working on a blog and I want users to be able to comment on blogs with some extra mark up from ckeditor. So I have made a foreach statement to show all the comments and a textarea field with ckeditor per blog post. Now the strange thing is all works fine but the ckeditor works only with the first blog while the textareas are visible at all blogs.
This is the error the webinspector shows
Uncaught The editor instance "editor1" is already attached to the provided element.
here is my view
IEnumerable<Portfolio.Models.Messages>
#{
ViewBag.Title = "Home Page";
}
<script src="~/Scripts/Comments.js"></script>
<link rel="stylesheet" type="text/css" href="~/Content/css/Blog.css" />
#*Shows the blog posts that are posted to the database*#
#foreach (var messages in Model)
{
<div class="jumbotron opacity_container">
<div class="col-md-12">
<div class="panel panel-primary">
<div class="panel-heading">
#*Gets the title of the blog post*#
<h2 class="panel-title">
#messages.Title
</h2>
#messages.WhenCreated
</div>
#*Gets the body of the blog post and decodes the html of the
ckeditor*#
<div class="panel-body">
#Html.Raw(System.Web.HttpUtility.HtmlDecode(messages.Body))
</div>
</div>
</div>
#*this button gets the id from the database of the Message table
this helps to prevent that all the comments from all blogs gets
shown and thusshows only the comments that belong to the blog in
question*#
<button class="btn btn-primary" id="#messages.MessagesId"
onclick="ShowComments(this.id)">
Show Comments
</button>
#*this is the container where al the comments are placed in and
where you can post comments. The comments are placed in the Comment
partial view*#
<div class="hidden" id="Comm#(messages.MessagesId)">
#Html.Partial("_Comment")
#*this button gets the id from the database of the Message table
this helps to prevent that all the comments from all blogs gets
hidden and thushides only the comments that belong to the blog in
question*#
<button class="btn btn-primary" id="#messages.MessagesId"
onclick="HideComments(this.id)">
Hide Comments
</button>
</div>
</div>
}
The partialview is called in the div with the classname hidden.
this is my partial view
#model IEnumerable<Portfolio.Models.Messages>
#{
ViewBag.Title = "Home Page";
}
<link rel="stylesheet" type="text/css" href="~/Content/css/Blog.css" />
<script src="~/Scripts/ckeditor/ckeditor.js"></script>
<div class="row" id="CommentContainer">
<div class="col-md-12">
<h3>Post Comment</h3>
#*The form to post comments*#
#using (Html.BeginForm("Create", "Messages"))
{
<div class="form-group">
<label>Comment</label>
#Html.TextArea("editor1", htmlAttributes:
new { name = "editor1",
id = "editor1", rows = "10", cols = "180" })
</div>
<button type="submit" class="btn btn-primary"
id="PostButton">Post Comment
</button>
}
#*CKEditor script*#
<script>
CKEDITOR.replace('editor1');
</script>
<div class="row">
<div class="col-md-10">
#*Places al the comments and decodes the html from the
ckeditor*#
#foreach(var messages in Model)
{
<div class="well" id="CommentBox">
#Html.Raw(System.Web.HttpUtility.HtmlDecode
(messages.Body))
</div>
}
</div>
</div>
</div>
</div>
The ckeditor is placed inside the partial view that is placed inside the foreach loop. So what I dont get is why is the taxtarea is visible at all posts but the ckeditor not, while they are both inside the same foreach statement.
As Gyum Fox said all the CkEditors had the same id and that doesn't work because a id should be unique.
What I'm trying to do is when I am in Index page, if I click the Register button, then it will show modal popup dialog of register page form.
'Index.cshtml' is in 'Home' view which has there own controller(HomeController.cs) and 'Register.cshtml' (which we need to bring this in to modal pop up when we click register button in 'Index') is in 'Account' view that has 'AccountController.cs' to controlling of register part.
First we tried to make javascript in index to make when I click the register button then it will make dialog box with content which bring register view page url (by .load()).
However, when we filled out the form and click submit button in the register form, then, if it succeed to register, it is ok (because in controller makes that redirect to index page) but if it failed, what controller do is add some validation summary which said why it is failed and return partial view which makes redirect to register page. This means that it will go to register pager instead dialog change.
I knew why this happen because register form connects with register controller.
So what I am doing here is that, I made Register view to partial view in the Shared folder.
So I can bring this to the Index.cshtml more easier. (Also I changed making dialog box from custom javascript to using modal class in Bootstrap.)
Here is my _Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - My ASP.NET Application</title>
#Styles.Render("~/Content/css")
<link href="~/Content/jquery-ui.css" rel="stylesheet" />
#Scripts.Render("~/bundles/jquery")
<script src="~/Scripts/jquery-ui.js"></script>
#Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="navbar navbar-inverse">
<!--navbar-fixed-top not spanning rest of contents, change body margin in site.css to use-->
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("GT BookSwap", "Index", "Home", null, new { #class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>#Html.ActionLink("Sell Textbooks", "SellingPage", "SearchList")</li>
<li>#Html.ActionLink("Buy Textbooks", "BuyingPage", "SearchList")</li>
</ul>
#Html.Partial("_LoginPartial")
</div>
</div>
</div>
<div>
#RenderBody()
</div>
<div class="container body-content">
<hr/>
<footer>
<p>© #DateTime.Now.Year - GT Senior Design Group</p>
</footer>
</div>
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
</body>
</html>
Here is my _LoginPartial.cshtml
#using Microsoft.AspNet.Identity
#if (Request.IsAuthenticated)
{
using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", #class = "navbar-right" }))
{
#Html.AntiForgeryToken()
<ul class="nav navbar-nav navbar-right">
<li>
#Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Manage", "Account", routeValues: null, htmlAttributes: new { title = "Manage" })
</li>
<li>Log off</li>
</ul>
}
}
else
{
<ul class="nav navbar-nav navbar-right">
<li>Register</li>
<li>#Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li>
</ul>
}
And Here is my Index.cshtml
#{
Layout = "~/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Home Page";
}
<div class="mainheader">
<div class="container">
<h1>GT BookSwap Page</h1>
<p>Sign up for BongBong to sell your textbooks!</p>
<p>#Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" , #class = "btn btn-primary", data_toggle="modal", data_target="basicModal"})</p>
</div>
</div>
<div class="bluecontainer">
<div align="center">
<div class="container">
<h1>Search by Keyword</h1>
<form class="navbar-form" role="search">
<div class="form-group">
<input type="text" class="form-control" size=80 placeholder="Search by title, author or ISBN">
</div>
<button type="submit" class="btn btn-primary btn-large" style="width:100px; height:55px;">Search</button>
</form>
</div>
</div>
</div>
<div class="yellowcontainer">
<div align="center">
<div class="container">
<h1>Search by Course</h1>
<form class="navbar-form" role="search">
<div class="form-group">
<input type="text" class="form-control" size=80 placeholder ="Search by title, author or ISBN">
</div>
<button type="submit" class="btn btn-warning" style="width:100px; height:55px;">Search</button>
</form>
</div>
</div>
</div>
#{Html.RenderPartial("_Register");}
Here is my _Register.cshtml (which is partial view in Shared folder)
#model GTBookSwap.Models.RegisterViewModel
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="registerLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="registerLabel">Register</h4>
</div>
<div class="modal-body" id="Content">
<div class="container" id="regi">
#Html.AntiForgeryToken()
<h4>Create a new account.</h4>
<hr />
#Html.ValidationSummary()
<div class="form-group">
#Html.LabelFor(m => m.UserName, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.UserName, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.ConfirmPassword, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.ConfirmPassword, new { #class = "form-control" })
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" id="Register" class="btn btn-default" value="Register" />
</div>
</div>
</div>
</div>
</div>
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
<script type="text/javascript">
var RegisterURL = {
RegisterUrl: '#Url.Action("Register", "Account")'
};
$("#Register").click(function (e) {
var form = $(this);
//var model = #Html.Raw(Json.Encode(Model));
$.ajax({
url: RegisterURL.RegisterUrl, (????????)
type: 'POST',
cache: 'false', (?????????)
data: form.serialize(), (????????)
//dataType: "html",
sucess: function (result) {
(???????)
},
error: function (result) {
(?????????)
alert("Fail");
//$("#Content").text("qweqwe");
$("#Content").html(result);
//$('#Content').load('/Shared/_Register');
}
})
})
var repeatUrl = '#Url.Action("Register","Account")';
var previewContainer = $('#myModel #Content');
</script>
Here is My Register() in AccountController
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser() { UserName = model.UserName };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await SignInAsync(user, isPersistent: false);
return RedirectToAction("Index", "Home");
}
else
{
//return RedirectToAction("Index", "Home");
AddErrors(result);
}
}
// If we got this far, something failed, redisplay form
//return Redirect(Request.Url.ToString());
//return Json(model);
//return PartialView("_Register",model);
return PartialView(model);
//return View(model);
}
From the javascript in _Register.cshtml, I don't know what to put in URL and stuff.(Especially in ?????? part)
Also What I have to change for the controller that send errors to show in javascript code in _Register.cshtml?? so if js got the result then make whether send to index or stay with this model popup register form because it is failed.
What I'm trying to do is open modal popup of register in index and even it failed or not, do not refresh to move site to register page, just stay on the popup and change only content.
Please!! Thanks.
Here is some my code regarding your question, tried to do same thing so if u can modify it by your requirements you should have found solution.
#model RegisterViewModel
input.input-validation-error,
textarea.input-validation-error,
select.input-validation-error {
background: #FEF1EC;
border: 1px solid #CD0A0A;
}
.validation-summary-errors ul li:nth-child(-n+4) {
display: none;
}
.validation-summary-valid {
display: none;
}
.validation-summary-errors {
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
border: 1px solid;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
color: #b94a48;
background-color: #FEF1EC;
border-color: #FEF1EC;
display: inline-block;
width: 100%;
height: 30px;
font-size: .9em;
padding: 7px;
}
.field-validation-error {
display: none;
}
</style>
#using (Ajax.BeginForm("Register", "Account", new AjaxOptions { HttpMethod = "Post"}))
{
#Html.AntiForgeryToken()
//Removed code for simplicity
<br />
#Html.ValidationSummary(false, "The highlighted fields are required!")
<br />
<p>
<input class="btn btn-lg btn-success btn-block" type="submit" value="Sign Up" />
</p>
}
I have the following:
_ImageGalleryPartial
#if (Model != null)
{
foreach (var item in Model)
{
#Html.Partial("_ImageItem", item);
}
}
_ImageItemPartial
#model WebsiteEngine.Models.PortfolioImage
#{
string url = VirtualPathUtility.ToAbsolute(String.Format("~/{0}", Html.DisplayFor(m => m.FileName)));
}
#using (Html.BeginForm("DeleteImage", "Portfolio", FormMethod.Post, new { #class = "deleteImageForm" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true);
#Html.HiddenFor(m => m.Name)
#Html.HiddenFor(m => m.FileName)
#Html.HiddenFor(m => m.Order)
#Html.HiddenFor(m => m.PortfolioID)
#Html.HiddenFor(m => m.PortfolioImageID)
<div class="span3">
<div class="item">
<a class="fancybox-button" data-rel="fancybox-button" title="Photo" href="#url">
<div class="zoom">
<img src="#url" alt="Photo" />
<div class="zoom-icon"></div>
</div>
</a>
<div class="details">
<i class="icon-remove"></i>
</div>
</div>
</div>
}
When I inspect the page elements using Chrome dev tools, the first element is missing the surrounding form. If I inspect the page source (using right) click then the form is there. This lead me to believe some JS was removing the form so I disabled JS but it was still missing.
If change _ImageGalleryPartial so it's like this (notice the addition of an empty model):
#if (Model != null)
{
#Html.Partial("_ImageItem", new WebsiteEngine.Models.PortfolioImage());
foreach (var item in Model)
{
#Html.Partial("_ImageItem", item);
}
}
Then all the "correct" elements get a form but again, this first item doesn't.
I'm still inclined to think this is a JS issue but I'm a little stumped as disabling JS doesn't fix it. Is this some off behaviour with MVC?
Just to note, I have simplified my layout above, I do actually have one or 2 nested forms but assume that's Ok as everything else is Ok, it's just this first partial that's broken.
Any ideas?
Html forms can't be nested.
Chrome will ignore illegal tags, thus they are not showing.
You can read this post for further information.
I would like to confirm if this limitation is by design or if I'm doing something wrong:
I have a View with two RenderPartials:
#model Heelp.ViewModels.CompanyIndexViewModel
#{ Html.RenderPartial(MVC.Company.Views.IndexSearch, Model.SearchViewModel); }
#{ Html.RenderPartial(MVC.Company.Views.IndexMap, Model.MapViewModel); }
In the first Partial View I have an Ajax.BeginForm:
#model Heelp.ViewModels.CompanyIndexSearchViewModel
#using (Ajax.BeginForm(MVC.Company.CategoryGetAllBySearch(), new AjaxOptions { UpdateTargetId = "searchCompanyResults", InsertionMode = InsertionMode.Replace }, new { #id = "searchBoxWrap" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(m => m.IsCenterFromUser)
#Html.HiddenFor(m => m.CenterLat)
#Html.HiddenFor(m => m.CenterLng)
#Html.HiddenFor(m => m.Zoom)
#Html.HiddenFor(m => m.SearchRadius)
#Html.TextBoxFor(m => m.Search, new { #placeholder = #HeelpResources.CompanyIndexViewSearchPlaceholder })
<input type="button" value="«" id="clearKeywords"/>
#Html.TextBoxFor(m => m.Location, new { #placeholder = #HeelpResources.CompanyIndexViewLocationPlaceholder })
<input type="button" value="«" id="clearLocation"/>
<input type="button" value="X" id="hereButton"/>
<input type="submit" value="#HeelpResources.CompanyIndexViewSearchButtonLabel"/>
}
<div id="searchCompanyResults" class="clearfix" style="z-index: 10; position: absolute; width: 400px;"></div>
The Ajax.BeginForm generates a PartialView in the searchCompanyResults div with a list of Ajax.ActionLink's:
#model Heelp.ViewModels.CategoryGetAllBySearchListViewModel
<p class="float-left margin-top align-left"><span>Encontrámos <em>#Model.TotalSearchCount</em> resultados nas categorias:</span></p>
<div class="clear-both">
<div id="searchResultsList" class="float-left">
<ul>
#foreach (var item in Model.CategoryGetAllBySearch)
{
<li>
#Ajax.ActionLink(
String.Format("{0} {1} ver »", item.SearchCount, item.Name),
MVC.Company.GetAllByCategory(item.Id, Model.Search, Model.Location, Model.IsCenterFromUser, Model.CenterLat, Model.CenterLng, Model.SearchRadius),
new AjaxOptions { OnBegin = "CompanyGetAllByCategoryOnBegin(" + item.Id + ")", OnSuccess = "CompanyGetAllByCategoryOnSuccess" })
</li>
}
</ul>
</div>
</div>
The problem here is that, if I don't include a link to "< script src="~/Scripts/jquery.unobtrusive-ajax.min.js" >" in the PartialView the Action.Link returns the Json text.
EDIT: One I detected is that when I click the Action.Link, the submit is made 2 times the first time, and 4 the second, and on and on growing, why?
Do I have to do this?
If you want use Ajax.BeginForm, Ajax.ActionLink and others from Ajax you should include jquery.unobtrusive-ajax.js file in your layout. It contains code that intercept click on link and submit of the form by cancel action and make it over AJAX.
You don't need include that file in partial views twice.