I have a form inside a modal popup, The user can enter text in a text box and click a plus button which dynamically adds the text they have typed in to a div so they can then proceed to add another one.
<div class="form-group">
<label class="control-label col-sm-4" for="prefix">
Cast <span style="color:red">*</span>
</label>
<div class="col-sm-5">
<input type="text" class="form-control col-sm-5" id="Cast" />
</div>
<div class="col-sm-1">
<button type="button" id="btnNewCast" class="btn btn-default">+</button>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-4" for="prefix"></label>
<div class="col-sm-6" id="newCast">
</div>
</div>
As shown here:
The NewCast is where I display the entered value by jquery.
When they click btnNewCast the following script is called
$("#btnNewCast").click(function () {
$("#newCast").append("<span class='label label-success label-as-badge custom-line-height' id='cast[]'><i class='glyphicon glyphicon-tag'></i> "+ $("#Cast").val() + "</span><br/>");
$("#Cast").val('');
});
Which looks like this:
The HTML is as follows:
<span id="cast[]" class="label label-success label-as-badge custom-line-height">
<i class="glyphicon glyphicon-tag"></i>
They Appear Here
</span>
When they press submit on on the form I pass the values back as shown here:
$("#btnAddMovie").click(function() {
$.ajax({
url: '/Movies/Add',
//data: $('NewMovie').serialize(),
data: { "Title": $("#Title").val(), "Classification": $("#Classification").val(), "Rating": $("#Rating").val(), "ReleaseDate": $("#ReleaseDate").val(), "Cast": $("#Cast").val() },
cache: false,
type: "POST",
success: function (result) {
if (result.success) {
}
},
error: function (result) {
alert("Error");
}
});
});
Which get mapped to my Model, and is working correctly.
Controller:
[HttpPost]
public ActionResult Add(Movie model)
{
return View();
}
My Model is declared like this:
public int MovieId { get; set; }
public int Rating { get; set; }
public int ReleaseDate { get; set; }
public string Title { get; set; }
public string Classification { get; set; }
public string Genre { get; set; }
public string[] Cast { get; set; }
The issue I have is as you can see Cast is a string array, the items the user enters (which is shown in the pictures) I'm trying to map them all to the Cast string array when they post.
I have tried
"Cast": $("#cast[]").val()
But I get a jquery error when posting, unrecognized expression
I can't get it to map correctly..
** Update** Complete post method
$("#btnAddMovie").click(function () {
var stringArr = $('span[data-id="cast[]"]').map(function() {
return $(this).text().trim();
});
$.ajax({
url: '/Movies/Add',
//data: $('NewMovie').serialize(),
data: { "Title": $("#Title").val(), "Classification": $("#Classification").val(), "Rating": $("#Rating").val(), "ReleaseDate": $("#ReleaseDate").val(), "Cast": stringArr },
cache: false,
type: "POST",
success: function (result) {
if (result.success) {
}
},
error: function (result) {
alert("Error");
}
});
});
Few issues :
<span> does not have .val() (value), use text().
The error
Unrecognized expression
Is because : [] - special chars are not allowed in plain #.. selectors. Use [id=""]
So use map() to iterate over this.
var stringArr = $('span[id="cast[]"').map(function(){
return $(this).text().trim();
});
Also, the way you are creating span through jQuery, the ID = cast[] is getting duplicated, and Duplicated Ids is Invalid markup. Use class attribute or data-* attributes like data-id="cast[]. The code would then be :
var stringArr = $('span[data-id="cast[]"').map(function(){
return $(this).text().trim();
});
Demo -
Related
I am developing an ASP.NET core Razor application and I have a form that I am posting, but I don't want the page to reload on submit. I read that this can be avoided by using Ajax, but i'm not sure how to implement this.
This is my form:
<form id="bankDropdown" method="post">
<div>
<label class="ratings-text" for="bank">Select Bank:</label>
<select name="BankOptions" class="form-control ratings-text" style="width:21%" id="bank">
#foreach (var bank in Model.BankLists)
{
<option name="BankOptions" value="#bank.ShortName" id="selection">#bank.ShortName</option>
}
</select>
</div>
<br />
<div>
<label>Enter Start Date:</label>
<input type="date" asp-for="DateSelect.DateMonthYear1" class="DateMonthYear" name="DateMonthYear1">
<i data-toggle="tooltip" title="Set to first day of the month for optimal results" class="far fa-question-circle"></i>
</div>
<br />
<div>
<label>Enter End Date:</label>
<input type="date" asp-for="DateSelect.DateMonthYear" class="DateMonthYear" name="DateMonthYear" required>
<i data-toggle="tooltip" title="Set to last or current day of the month for optimal results" class="far fa-question-circle"></i>
</div>
<br />
<div>
<input class="ratings-button" type="submit" value="Submit"/>
</div>
</form>
This is my POST function in my page model:
public IActionResult OnPost(string DateMonthYear, string DateMonthYear1, string BankOptions)
{
CurrentDate = string.Format(DateMonthYear);
SelectBank = BankOptions;
BankLists = ModelService.RunBankList();
TotalBankCollections = ModelService.RunTotalBankCollection1(DateMonthYear);
TotalTransactionCounts = ModelService.RunTotalTransactionCount1(DateMonthYear1, DateMonthYear);
long floatTotalCount = 0;
int intVolumeCount = 0;
string stringTotalVolume = "";
//get individual bank monthly collections
foreach (var collection in TotalBankCollections)
{
if (BankOptions == collection.ShortName)
{
string myBank = collection.TotalCollection;
BankCollection = Convert.ToDecimal(myBank).ToString("#,###,###.##");
}
}
//get total collections from all the banks
foreach (var collection in TotalBankCollections)
{
floatTotalCount += (long)Convert.ToDouble(collection.TotalCollection);
string stringTotalCount = Convert.ToDecimal(floatTotalCount).ToString("#,###,###.##");
TotalCollectionCount = stringTotalCount;
}
//get individual monthly volume collections
foreach (var collection in TotalTransactionCounts)
{
if (BankOptions == collection.ShortName)
{
string myBank = collection.TotalCount;
MonthlyVolumeCount = Convert.ToDecimal(myBank).ToString("#,##0");
}
}
//get total transactions of all banks
foreach (var collection in TotalTransactionCounts)
{
intVolumeCount += int.Parse(collection.TotalCount);
stringTotalVolume = intVolumeCount.ToString("#,##0");
TotalVolumeCount = stringTotalVolume;
}
return Page();
}
This is what I have so far, I have never used Ajax before and I have a project deadline:
$.ajax({
type: "POST",
url: "/Identity/Account/Ratings",
contentType: 'application/json; charset=utf-8',
dataType: "json",
success: function (response) {
alert(response);
},
failure: function (response) {
alert(response);
}
});
Thanks for the help.
If you want to use ajax with post method in razor page,here is a demo:
TestFormPost.cshtml(script):
$("#bankDropdown").on('submit', function (e) {
e.preventDefault();
$.ajax({
type: "POST",
url: "",
data: $("#bankDropdown").serialize(),
headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
success: function (data) {
}
});
})
TestFormPost.cshtml.cs:
public class TestFormPostModel : PageModel
{
[BindProperty]
public List<Bank> BankLists { get; set; }
[BindProperty]
public DateSelect DateSelect { get; set; }
public IActionResult OnGet()
{
BankLists = new List<Bank> {
new Bank{ ShortName="bank1"},
new Bank{ ShortName="bank2"},
new Bank{ ShortName="bank3"}
};
return Page();
}
public IActionResult OnPost(string DateMonthYear, string DateMonthYear1, string BankOptions) {
return Page();
}
}
public class Bank
{
public string ShortName { get; set; }
}
public class DateSelect
{
public string DateMonthYear { get; set; }
public string DateMonthYear1 { get; set; }
}
result:
you can prevent form submission by
$('form').on('submit',function(e){
e.preventDefault();
////then ajax call
})
I was trying to pass a whole object to the jsonresult method. but there are errors that occur. It might be the way I bound it but I'm not sure. I'm new to JS and KOJS. Once the Login button, which is bound to the LogUser method, is clicked, it should call the Authenticate(Employee p) method.
here is my class model
public class Employee
{
[Key]
public long AutoId { get; set; }
[Required]
Display(Name = "Employee ID")]
public string EmployeeId { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string EmployeePassword { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
}
this is my knockoutjs view model
$(function () {
ko.applyBindings(LoginVm);
});
//VIEW MODEL. MODEL IS BELOW THIS
var LoginVm = {
thisEmp: ko.observable(EmpObject),
LogUser: function () {
var self = this;
//trying to check if thisEmp properties has values by alerting
alert("ID: " + thisEmp.EmployeeId() + " Password: " + thisEmp.EmployeePassword());
$.ajax({
url: '/Employee/AuthenticateUser',
type: 'POST',
dataType: 'json',
data: ko.toJSON(thisEmp),
contentType: 'application/json',
success: function (errorMsg) {
if (errorMsg === '') {
}
}
});
}
};
//MODEL
var EmpObject = {
EmployeeId: ko.observable(''),
EmployeePassword: ko.observable('')
}
this is my view and how I bound the properties
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Employee</legend>
<div class="editor-label">
#Html.LabelFor(model => model.EmployeeId)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.EmployeeId, new { data_bind="value: thisEmp.EmployeeId()"})
#Html.ValidationMessageFor(model => model.EmployeeId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.EmployeePassword)
</div>
<div class="editor-field">
#Html.PasswordFor(model => model.EmployeePassword, new { data_bind="value: thisEmp.EmployeePassword()"})
#Html.ValidationMessageFor(model => model.EmployeePassword)
</div>B
<p>
#*<input type="submit" value="Create"/>*#
<input type="button" value="Login" data-bind="click: LogUser"/>
</p>
</fieldset>
}
this is the error
Uncaught TypeError: Unable to process binding "value: function (){return thisEmp().EmployeeId }"
Message: Cannot read property 'EmployeeId' of undefined
at value (eval at createBindingsStringEvaluator
The error is being thrown because you have defined LoginVm beforeEmpObject. You need to change the order they are declared.
Are you sure this is the code that produced this error? In your view you're binding thisEmp.EmployeeId() but th error says it's unable to bind thisEmp().EmployeeId. I think you tried both of them and the error still persisted. Either way, there is no need to make thisEmp an observable. It's enough that the properties are observables.
So, change your code to:
$(function () {
ko.applyBindings(new LoginVm());
});
//MODEL
var EmpObject = {
EmployeeId: ko.observable(''),
EmployeePassword: ko.observable('')
}
//VIEW MODEL. MODEL IS BELOW THIS
var LoginVm = function() {
var self = this;
self.thisEmp = EmpObject;
self.LogUser = function () {
var self = this;
//trying to check if thisEmp properties has values by alerting
alert("ID: " + self.thisEmp.EmployeeId() + " Password: " + self.thisEmp.EmployeePassword());
$.ajax({
url: '/Employee/AuthenticateUser',
type: 'POST',
dataType: 'json',
data: ko.toJSON(self.thisEmp),
contentType: 'application/json',
success: function (errorMsg) {
if (errorMsg === '') {
}
}
});
}
};
And change the bindings in view to:
#Html.TextBoxFor(model => model.EmployeeId, new { data_bind="value: thisEmp.EmployeeId"})
#Html.PasswordFor(model => model.EmployeePassword, new { data_bind="value: thisEmp.EmployeePassword"})
When clicking a button I am calling a web api with ajax. My form is using JqueryVal, to make form validations, according to my viewmodel data annotations.
My problem is that when I click the button "Listo" in my form, it calls my API, inspite of jqueryval is marking an error( selecting a file is required)
This is my code:
My viewmodel that contains data annotations(the dataannotations are used along with the jquery.validate.js and jquery.validate.unobtrusive.js. As you can see, it is working, but is not preventing the API from being called):
public class CursoViewModel
{
public Guid Id { get; set; }
[MaxLength(125)]
public string Titulo { get; set; }
[Required]
public string Descripcion { get; set; }
[Required(ErrorMessage ="selecciona una imagen para tu curso")]
[DataType(DataType.Upload)]
public HttpPostedFileBase Imagen { get; set; }
}
The class posted to my api
public class person
{
public string name { get; set; }
public string surname { get; set; }
}
The Api code
[HttpPut]
[Route("api/ProfesorCurso/test")]
public string Put(person p)
{
return p.name + p.surname;
}
My View
#model project.ViewModels.CourseViewModel
<form id="Editcurso" method="post" action="#">
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "Please fix the following errors.")
<div class="container">
<div class="form-group">
#Html.LabelFor(c=>c.Titulo)
#Html.TextBoxFor(c => c.Titulo, new {id="titulo", #class="form-control"})
#Html.ValidationMessageFor(m => m.Titulo)
</div>
<div class="form-group">
#Html.LabelFor(c => c.Descripcion)
#Html.TextAreaFor(c => c.Descripcion, new {id="descripcion", #class = "form-control" })
#Html.ValidationMessageFor(m => m.Descripcion)
</div>
<div class="thumbnail" id="imagencurso"></div>
<div class="form-group">
#Html.LabelFor(m => m.Imagen)
#Html.TextBoxFor(m => m.Imagen, new {id="imagen" ,type = "file", data_rule_validCustomer = "true" })
#Html.ValidationMessageFor(m => m.Imagen)
</div>
<button id="submiter" type="submit" class="btn btn-primary">Listo!</button>
</div>
</form>
The scripts in the view
#section scripts
{
#Scripts.Render("~/bundles/jqueryval")
<script>
$(document).ready(function () {
$("#submiter").click(function () {
jQuery.support.cors = true;
var person = new Object();
person.name = "Sourav";
person.surname = "Kayal";
$.ajax({
url: '/api/ProfesorCurso/test',
type: 'PUT',
dataType: 'json',
data: person,
success: function (data) {
console.log(data);
return false;
},
error: function (x, y, z) {
alert('error al postear');
return false;
}
});
});
});
</script>
}
What can I do to prevent ajax to call my api when clicking my form button, if there are Jquery validation errors?
thanks
You should be handling the .submit() event of the form, and then your can check .valid(), and if not cancel the ajax call. Note you should also be cancelling the default submit.
$('#Editcurso').submit(e) {
e.preventDefault(); // prevent the default submit
if (!$(this).valid()) {
return; // exit the function and display the errors
}
....
$.ajax({
....
});
}
As a side note, there is no point adding new { id="titulo" } etc - the HtmlHelper methods that generate form controls already add an id attribute based on the property name
I've been investigating for this issue for more than 12 hours with no clue for any solution. I have good knowledge about jtable and I've been using it for long time. I have an ordinary div which I want to build it using jtable, so I copied the code from an old working sample in my application and edited it, but there is a javascript error appear in the console which prevents the data to show in the table:
Uncaught TypeError: Cannot read property 'data' of undefined jquery Jtable
here is my html page:
#model Tuple<List<SIO.Core.Entities.Group>, List<SIO.Core.Entities.WorkFlow>>
#section JavaScript
{
<script type="text/javascript" src="#Url.Content("/Scripts/GroupHandler.js")"></script>
<script type="text/javascript" src="#Url.Content("/Scripts/jquery-ui.js")"></script>
<script type="text/javascript" src="#Url.Content("/Scripts/jquery.jtable.js")"></script>
}
#{
ViewBag.Title = "المجموعات";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div id="divBackgroundtask" style="display: none;">
</div>
<div id="indx_divtask">
<section class="col-md-8 taskPoolfilterSection">
<div class="form-group">
<div class="border-top">
</div>
<div id="filter" class="panel-body margin-bottom">
<header class="panel-heading containt-border">
#ViewBag.Title
</header>
</div>
</div>
<!-- /.panel-body -->
<div id="divPleaseWaittask" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="load_div col-sm-offset-2 col-sm-5">
<div class=" row col-sm-2 col-sm-offset-9">
<img src="~/Images/Loading.gif" />
</div>
<div class="row col-sm-12 txt_wait">
<b>برجاء الإنتظار حتى إكمال العملية</b>
</div>
</div>
</div>
</section>
<div id="GroupsContainer" class="table-responsive">
</div>
And here is my javascript code to build jtable:
(document).ready(function () {
$('#GroupsContainer').jtable({
paging: true,
sorting: true,
messages: {
close: 'اغلاق',
pagingInfo: 'عرض {0}-{1} من {2}',
pageSizeChangeLabel: 'تعداد الصف',
noDataAvailable: 'لا يوجد بيانات للعرض!',
gotoPageLabel: 'الذهاب الى صفحة',
serverCommunicationError: 'حدث خطأ ما اثناء الإتصال...',
},
actions: {
//listAction: '/TaskPool/GetTasks?isAdmin=' + IsAdmin,
listAction: function (postData, jtParams) {
// alert("Loading...");
PleaseWaitDialogtask.show(true);
return $.Deferred(function ($dfd) {
$.ajax({
url: '/Group/GetAllGroups?' + 'jtStartIndex=' + jtParams.jtStartIndex + '&jtPageSize=' + jtParams.jtPageSize + '&jtSorting=' + jtParams.jtSorting,
type: 'Get',
dataType: 'json',
data: postData,
success: function (data) {
$dfd.resolve(data);
PleaseWaitDialogtask.show(false);
},
error: function () {
$dfd.reject();
}
});
});
},
},
fields: {
ID: {
key: true,
list: false
},
GroupName: {
title: 'اسم المجموعة'//,
//width: '40%'
},
GroupDisc: {
title: 'وصف المجموعة'//,
//width: '40%'
},
Link: {
title: '',
display: function (data) {
if (data.isRedirect) {
window.location.href = data.redirectUrl;
}
}
},
}
});
$('#GroupsContainer').jtable('load');
$('.jtable')[0].className = $('.jtable')[0].className + " table table-striped table-bordered table-hover";
});
This is the line which caused the error:
$dfd.resolve(data);
And here is my action method to retrieve the records:
[HttpGet]
public JsonResult GetAllGroups(int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = null, string rangeSt = "", string rangeEd = "")
{
try
{
LogHelpper.LogMessage("GroupContorller GetAllSystemUsers Post Method Started", EventLogEntryType.Information, log);
GroupManager groupManager = new GroupManager();
List<Group> groups = groupManager.SkipAndTake(jtStartIndex, jtPageSize);
List<GroupCustomViewModel> groupCustomViewModel = groups.Select(group => new GroupCustomViewModel(group)).ToList();
LogHelpper.LogMessage("GroupContorller GetAllGroups Post Method Ended", EventLogEntryType.Information, log);
return Json(new { Result = "OK", Records = groupCustomViewModel , TotalRecordCount = groupCustomViewModel .Count }, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
LogHelpper.LogMessage("Error Message", EventLogEntryType.Error, log);
LogHelpper.LogException(ex, EventLogEntryType.Error, log);
return Json(new { Result = "ERROR", Message = ex.Message }, JsonRequestBehavior.AllowGet);
}
}
And here is my model:
public class GroupCustomViewModel
{
#region properties
/// <summary>
/// Gets or sets the GoupIDPK.
/// </summary>
/// <value>The GoupIDPK.</value>
public int GoupIDPK { get; set; }
/// <summary>
/// Gets or sets the GroupName.
/// </summary>
/// <value>The GroupName.</value>
public string GroupName { get; set; }
/// <summary>
/// Gets or sets the GroupDisc.
/// </summary>
/// <value>The GroupDisc.</value>
public string GroupDisc { get; set; }
public string EditHyperlink { get; set; }
public string DeleteHyperlink { get; set; }
public string DetalisHyperlink { get; set; }
public bool DefaultGroup { get; set; }
#endregion
}
Sorry if the question is too long but I don't know where the error would be so I
posted all code required to do the task.
Finally I found where the problem is!! ... In jTable definition at fields sectionID but the model field name is GroupIDPK so changing jTable field ID to GroupIDPK solved the problem
I am new to both asp.net MVC and JQuery so be gentle.
I am trying to use a HTTP Post to update my contact form, used to send an email, using AJAX. I have seen lots of posts but what I want seems specific and I cant seem to find anything relevant.
The down low: I have a layout page which has the header, renders the body and has my footer in. My footer contains the form I want to submit. I want to submit this form without refreshing the whole page. The layout page:
<div id="footer">
#{Html.RenderAction("Footer", "Basic");}
</div>
<p id="p"></p>
I have a model for this form to send an email.
namespace SimpleMemberShip.Models
{
public class EmailModel
{
[Required, Display(Name = "Your name")]
public string FromName { get; set; }
[Required, Display(Name = "Your email"), EmailAddress]
[StringLength(100, ErrorMessage = "The email address entered is not valid")]
public string FromEmail { get; set; }
[Required]
public string Message { get; set; }
}
The footer:
<h2> footer yo !</h2>
#Html.ValidationSummary()
<fieldset>
<legend>Contact Me!</legend>
<ol>
<li>
#Html.LabelFor(m => m.FromEmail)
#Html.TextBoxFor(m => m.FromEmail)
</li>
<li>
#Html.LabelFor(m => m.FromName)
#Html.TextBoxFor(m => m.FromName)
</li>
<li>
#Html.LabelFor(m => m.Message)
#Html.TextBoxFor(m => m.Message)
</li>
</ol>
<button id="submit"> Submit </button>
</fieldset>
controller:
[ChildActionOnly]
public ActionResult Footer()
{
return PartialView("~/Views/Shared/_Footer.cshtml");
}
[HttpPost]
public ActionResult Footer(EmailModel model)
{
return PartialView("~/Views/Shared/_Footer.cshtml");
}
I want to use the model validation and everything to be the same or similar as if the form was posted normally through the server.
Edit:
My new code, which works great! but it only works once, when the button is clicked again nothing happens. Anyone know why?
<script type="text/javascript">
$("#submit").click(function () {
$("#footer").html();
var url = '#Url.Action("Footer", "Basic")';
$.post(url, { FromName: $("[name=FromName]").val(), FromEmail: $(" [name=FromEmail]").val(), Message: $("[name=Message]").val() }, function (data) {
$("#footer").html(data);
});
var name = $("[name=FromName]").val();
$("#p").text(name);
});
</script>
new Edit:
did some research and using
$("#submit").live("click",function () {
instead of
$("#submit").click(function () {
seemed to do the trick.
<script type="text/javascript">
$("#submit").live("click",function () {
$('.validation-summary-errors').remove();
var url = '#Url.Action("Footer", "Basic")';
$.post(url, { FromName: $("[name=FromName]").val(), FromEmail: $("[name=FromEmail]").val(), Message: $("[name=Message]").val() }, function (data) {
$("#footer").html(data);
});
});
</script>
ended up with this but will try the "serialize()" option next time.
controller was changed to this without the [ChildActionOnly] and works perfect now
[HttpPost]
public ActionResult Footer(EmailModel model)
{
return PartialView("~/Views/Shared/_Footer.cshtml");
}
Thank you everyone that helped!
Change the [ChildActionOnly] to [HttpGet] in the controller
You can pass model data to controller by doing the following steps
1. Get the input values on click of submit and sent to the Footer action in controller
$("#submit").click(function () {
var FromEmailValue = $('#FromEmail').val();
var FromNameValue = $('#FromName').val();
var MessageValue = $('#Message').val();
var url = '#Url.Action("Footer", "Basic")';
$.ajax({
url: urlmodel,
data: { FromName: FromNameValue, FromEmail: FromEmailValue, Message: MessageValue},
cache: false,
type: "POST",
success: function (data) {
do something here
}
error: function (reponse) {
do something here
}
});
});
In the controller
``
[HttpGet]
public ActionResult Footer()
{
return PartialView("~/Views/Shared/_Footer.cshtml");
}
[HttpPost]
public ActionResult Footer(string FromName = "", string FromEmail = "", string Message = "")
{
//for ajax request
if (Request.IsAjaxRequest())
{
do your stuff
}
}