I want to enter values to my table "Categories" so as not to reload the page and keep the user always in sight, for this I want to use Ajax + Jquery, the exercise seems simple but it has me crazy, you enter category names in an input and you want to show a <div> for your confirmation (success) or failure (danger) depending on the case, something like that ....
The problem is that my Javascript code does not do anything, it is not even entering the Create method
I enclose my view create.html:
<head>
<script src="~/Scripts/jquery-1.12.4.js"></script>
<script src="~/Scripts/jquery-1.12.4.min.js"></script>
</head>
<body>
<div id="div-alerta">
<label id="mensaje-alerta"></label>
</div>
<hr />
#Html.LabelFor(model => model.v_Nombre, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input class="form-control" type="text" id="txtNombre" />
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="button" value="Crear" id="btnCrearCategoria" class="btn btn-outline-success btn-lg" />
</div>
</div>
</body>
</html>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script>
$(function () {
$("#btnCrearCategoria").click(function () {
var url = "#Url.Action("Create", "Categorias")";
var nombre = $("#txtNombre").val();
var data = { v_Nombre: nombre };
$.post(url, data).done(function (data) {
if (data.Ok) {
$("#div-alerta").removeClass("alert-danger").addClass("alert-success").slideDown(100);
}
else {
$("div-alerta").removeClass("alert-success").addClass("alert-danger").slideDown(100);
}
$("#mensaje-alerta").html(data.Mensaje)
})
})
})
</script>
}
This is my object category.cs:
public class Categoria
{
[Key]
public int Kn_CodigoCategoria { get; set; }
[Required(ErrorMessage = "El campo {0} es obligatorio")]
[MaxLength(40, ErrorMessage = "El campo {0} debe tener un máximo de {0} caracteres")]
[Column(TypeName = "VARCHAR")]
[Index("Categoria_v_Nombre_Index", IsUnique = true)]
[Display(Name = "Nombre Categoria")]
public string v_Nombre { get; set; }
}
and this is my create method that returns a Json:
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult Create(Categoria categoria)
{
var resultado = new BaseRespuesta();
try
{
db.Categorias.Add(categoria);
db.SaveChanges();
resultado.Mensaje = "Categoria creada correctamente";
resultado.Ok = true;
}
catch (Exception ex)
{
resultado.Mensaje = ex.Message;
resultado.Ok = false;
}
return Json(resultado);
}
I occupy a class called BaseResponse to see messages of success or failure of my operation:
public class BaseRespuesta
{
public bool Ok { get; set; }
public string Mensaje { get; set; }
}
My expected behavior: When entering a value in the text box, show me a div (success or failure) with the corresponding message
My behavior obtained: entering a value in the input does nothing
what am I doing wrong? I'm missing something in my code? it's the first time I work with Ajax calls ... should I load a partial view? any help for me?
It looks like this might be wrong:
var url = "#Url.Action("Create", "Categorias")";
To pass in the string "Categorias" to the action "Create", it would be something like the following where you would create an 'anonymous' type. Maybe try:
var url = "#Url.Action("Create", new { categoria = "Categorias"})";
You have double quotes that aren't being escaped:
<script>
$(function () {
$("#btnCrearCategoria").click(function () {
**var url = "#Url.Action("Create", "Categorias")";**
var nombre = $("#txtNombre").val();
var data = {
v_Nombre: nombre
};
$.post(url, data).done(function (data) {
if (data.Ok) {
$("#div-alerta").removeClass("alert-danger").addClass("alert-success").slideDown(
100);
} else {
$("div-alerta").removeClass("alert-success").addClass("alert-danger").slideDown(
100);
}
$("#mensaje-alerta").html(data.Mensaje)
})
})
})
</script>
You need to either escape them or use single quotes around the whole string:
var url = '#Url.Action("Create", "Categorias")';
or
var url = "#Url.Action(\"Create\", \"Categorias\")";
The second option can get tricky trying to manage all of the "\" backslashes so I would recommend the first option.
The element [ValidateAntiForgeryToken] as decoration of my JsonResult blocked my Javascript action, eliminating this decoration and leaving only [HttpPost] worked for me !!
Related
I have a functionality where I append a select html when a button is clicked using jQuery. I already have a select which uses a asp-item tag helper to fill it with my corresponding model. The platform I'm using is asp-net core 2.2 and I'm using a razor page for my page.
My question is how do I edit my jQuery so that when I clicked the button, the asp-item is already loaded into the select?
Here is my jQuery code:
$("#AddButton").click(function () {
tc = tc + 1;
$("#totalContacts").val(tc)
$(".addselection").append('<div> <select class="form-control" name="[' + (tc) + '].DriverID" asp-for="TripDrivers.DriverID" asp-items="Model.DriverList" > <option value = ""> Select a driver </option></select></div>')
});
and this is my OnGet to load the items
public IActionResult OnGet()
{
DriverList = _context.Drivers.Select(a =>
new SelectListItem
{
Value = a.ID.ToString(),
Text = a.FullName
}).ToList();
}
This is my first ever question, so please bear with me if there are any grammatical errors or missing information. I'll add them if necessary.
EDIT: Here is the design I'm trying to do.
Once the plus button is clicked. It should add a row of dropdownlist each with the option being loaded from the list on the OnGet method.
ANOTHER EDIT: As per user #itminus instructions, I've created a one sample page and a partial view to apply the code given below.
Here is what my FirstPage.cshtml looks like
#page
#model MasigasigTrackingSystem.Pages.TestingPages.FirstPageModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>FirstPage</title>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script>
$("#AddButton").click(function () {
tc = tc + 1;
$("#totalContacts").val(tc)
$.ajax('?handler=DropdownList', {
method: "GET",
data: { tc: tc },
success: function (d) { $(".addselection").append(d); }
});
});
</script>
</head>
<body>
<button id="AddButton" class="btn" type="button">+</button>
#*<select asp-for="Mode" asp-items="Model.DropdownListViewModel.Drivers" class="form-control">
<option value="">Select a driver</option>
</select>*#
<div class="addselection">
<partial name="_SecondPage.cshtml" />
</div>
</body>
</html>
My FirstPageModel
namespace MasigasigTrackingSystem.Pages.TestingPages
{
public class FirstPageModel : PageModel
{
private readonly MasigasigTrackingSystem.Data.ApplicationDBContext _context;
public FirstPageModel(MasigasigTrackingSystem.Data.ApplicationDBContext context)
{
_context = context;
}
[BindProperty]
public Drivers Drivers { get; set; }
public List<SelectListItem> DriverList { get; set; }
[BindProperty]
public DropdownListViewModel DropdownListViewModel { get; set; }
public void OnGet()
{
DriverList = _context.Drivers.Select(a =>
new SelectListItem
{
Value = a.ID.ToString(),
Text = a.FullName
}).ToList();
DropdownListViewModel = new DropdownListViewModel();
DropdownListViewModel.Drivers = DriverList;
}
public IActionResult OnGetDropdownListAsync(int tc)
{
var list = _context.Drivers.Select(a => new SelectListItem
{
Value = a.ID.ToString(),
Text = a.FullName,
}).ToList(); // or filter by Where( ... tc...).ToList()
return Partial("/Pages/TestingPages/_SecondPage.cshtml", new DropdownListViewModel
{
Drivers = list,
ID = tc,
});
}
}
}
My partial _SecondPage
#using MasigasigTrackingSystem.Models
#model DropdownListViewModel
<div>
<select class="form-control dropdown" name="[#Model.ID].DriverID" asp-items="#Model.Drivers">
<option> Select a driver </option>
</select>
</div>
My DropdownlistViewModel
namespace MasigasigTrackingSystem.Models
{
public class DropdownListViewModel
{
public int ID { get; set; }
public IList<SelectListItem> Drivers { get; set; }
}
}
Here's a demo that gets the partial view dynamically from server.
Create a Handler OnGetDropdownListAsync(int tc) in your PageModel:
public class YourPageModel : PageModel
{
... other handler methods, e.g. OnGet() render the Index
public IActionResult OnGetDropdownListAsync(int tc)
{
var list = _context.Drivers.Select(a =>new SelectListItem{
Value = a.ID.ToString(),
Text = a.FullName,
}).ToList(); // or filter by Where( ... tc...).ToList()
return Partial( "/Pages/Shared/Selection.cshtml" , new DropdownListViewModel{
Drivers = list,
Index = tc,
});
}
}
Here the DropdownListViewModel is a plain ViewModel that holds the data:
public class DropdownListViewModel{
public IList<SelectListItem> Drivers{get;set;}
public int Index {get;set;}
}
Move your original html snippet within jQuery into a new partial view file: /Pages/Shared/Selection.cshtml
#using App.Pages
#model DropdownListViewModel
<div>
<select class="form-control dropdown" name="[#Model.Index].DriverID" asp-items="#Model.Drivers">
<option> Select a driver </option>
</select>
</div>
Finally, change your JavaScript to send an ajax request and update the UI in following way:
$("#AddButton").click(function () {
tc = tc + 1;
$("#totalContacts").val(tc)
$.ajax('?handler=DropdownList',{
method:"GET",
data:{ tc: tc },
success:function(d){ $(".addselection").append(d); }
});
});
[Edit]
You are passing currect ViewData to <partial> implicitly, which leads to this type error. You need change it to :
<partial name="/Pages/TestingPages/_SecondPage.cshtml" model="#Model.DropdownListViewModel" />
You're referencing an slim jQuery that doesn't have a ajax. Please change the script to <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>.
You're binding an event for #AddButton before this element has been created. You need wrap the js into a $(document).ready(function(){ .... }. You can also create a manually script after the #AddButton element. Or put the <script> into #section Scripts{} if you're using a default Layout which will make the script take effect after the page has been loaded.
Also you didn't initialize a tc variable.
In short, you need fix the bugs as below:
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$(document).ready(function(){
var tc = 0;
$("#AddButton").click(function () {
tc = tc + 1;
$("#totalContacts").val(tc)
$.ajax('?handler=DropdownList', {
method: "GET",
data: { tc: tc },
success: function (d) { $(".addselection").append(d); }
});
});
});
</script>
...
<div class="addselection">
<partial name="/Pages/TestingPages/_SecondPage.cshtml" model="#Model.DropdownListViewModel" />
</div
I have a requirement which I need to display price based on drop down selection. and that price comes from same db, when I click one Test from dropdown then respected price of that test should display in textbox.The value is binding in textbox after selecting option from dropdown also it is displaying after taking span but not displaying on textbox, please tell me solution because i want to display it only on textbox .
here is Error Image
Model class
public partial class TwoDDiagnostic
{
public int TwoD_ID { get; set; }
public string TwoDDiagnostic_Name { get; set; }
public string TwoD_Price { get; set; }
public Nullable<System.DateTime> TwoD_Date { get; set; }
public Nullable<int> centr_Id { get; set; }
}
Controller
IEnumerable<SelectListItem> selectList2D = from twod in db.TwoDDiagnostics
where twod.centr_Id == Id
select new SelectListItem()
{
Text = twod.TwoDDiagnostic_Name,
Value = twod.TwoDDiagnostic_Name
};
var lasttwoD = db.TwoDDiagnostics.Where(x => x.centr_Id == Id).OrderByDescending(c => c.TwoD_ID).Take(1).FirstOrDefault();
if (lasttwoD == null)
{
ViewBag.twoDID = new SelectList(selectList2D, "Value", "Text");
model.ViewModel_TwoDDiagnostic = null;
return View(model);
}
string twodname = (from sub in db.TwoDDiagnostics where sub.TwoD_ID == lasttwoD.TwoD_ID select sub.TwoDDiagnostic_Name).First();
ViewBag.twoDID = new SelectList(selectList2D, "Value", "Text", twodname);
View
<div class="form-inline">
<label for="inputEmail1" class=" col-lg-2 col-sm-4 control-label">2D Diagnostic Services</label>
<div class="col-lg-5">
#Html.DropDownListFor(model => model.PTwoDDiagnostic_name, (SelectList)ViewBag.twoDID, "- Select 2D Diagnostics -", new { #class = "form-control ", #id = "twopID", #onchange = "fill()" })
</div>
<div class="col-lg-3">
#*<span class="form-control" id="twoprice"></span>*#
#Html.TextBoxFor(model => model.PTwoDDiagnostic_price, new { #class = "form-control ", #id = "twoprice" , #onchange = "fill()"})
</div>
</div>
here is json method
public JsonResult GetTwoDPrice()
{
AllViewModel model = new AllViewModel();
Session["Two_D"] = model.TwoD_ID;
var id = (int)Session["Two_D"];
if (!string.IsNullOrEmpty(Session["Two_D"].ToString()))
{
//int Id = (int)Session["Two_D"];
var Record = (from patient in db.TwoDDiagnostics
where patient.TwoD_ID == id
select new
{
TwoD_ID = patient.TwoD_ID,
TwoD_Price = patient.TwoD_Price
}).FirstOrDefault();
return Json(Record, JsonRequestBehavior.AllowGet);
}
return Json("", JsonRequestBehavior.AllowGet);
}
here is a script
<script type="text/javascript">
$("#twopID").on('change', function (event) {
$.ajax({
url: "#Url.Action("GetTwoDPrice", "Center")",
type: "Get",
success: function (data) {
debugger;
console.log(data.TwoD_Price);
$('#twoprice').text(data.TwoD_Price);
}
});
});
</script>
You need to use the jquery val() method to set the Value for the TextBox. If you use text() method, it sets the innerText of the input element (in between the <input> and </input> HTML tags) which is applicable only for HTML Elements like span, label, h, div, etc.
$('#twoprice').val(data.TwoD_Price);
Im developing a mvc5 application. In a view, using jquery i generate html elements(dropdownlists and textboxes) dynamically.
View briefly
#using (#Html.BeginForm("Save", "Item"))
{
#Html.DropDownListFor(a => a.MainGrpId, new SelectList(ViewBag.mnGrpList, "MainGroupId", "MainGroupName"), " Select a MainGroup", new { Class = "form- control", title = "", style = "width:175px;height:30px; margin-top:6px;" })
#Html.DropDownListFor(a => a.SubGrpId, new SelectList(ViewBag.sbGrpList, "SubGroupId", "SubGroupName"), " Select a SubGroup", new { Class = "form-control", title = "", style = "width:175px;height:30px; margin-top:6px;" })
<div id="ss" class="col-md-6">
</div>
#Html.TextBoxFor(a=>a.ItemName, new { Class = "form-control", placeholder = " Item Name", TextMode = "MultiLine2", onkeyup = "return validateChar(this)", style = "width:175px;height:25px;" })
<input type="submit" value="Save" class="btn btn-success" />
}
Jquery
var ss = $('#ss');
$('#SubGrpId').change(function () {
$('#ss').empty();
$.ajax({
url: '#Url.Action("FillItem", "Item")', // dont hard code your url's
type: "GET",
dataType: "JSON",
data: { MnId: $('#MainGrpId').val(), SbId: $(this).val() }, // pass the selected value
success: function (y) {
$.each(y, function (l, u) {
// add the label
var label = u.Name;
var name = 'Field' + l;
var label = $('<label></label>').text(label).attr('for', name);
ss.append(label);
if (u.Options.length==0) {
// There is only one item and its for generating a textbox
var input = $('<input>').attr({ type: 'text', id: name, name: name });
ss.append(input);
} else {
// Its a select
var select = $('<select></select>').attr({ id: name, name: name });
// add each option
$.each(u.Options, function (i, option) {
select.append($('<option></option>').val(option.Value).text(option.Text));
})
ss.append(select);
}
});
},
error: function () {
alert("something wrong");
}
});
});
ItemViewModel
public class ItemViewModel
{
public string ItemName { get; set; }
public int MainGrpId { get; set; }
public int SubGrpId { get; set; }
public string Field0 { get; set; }
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }
public string Field4 { get; set; }
public string Field5 { get; set; }
}
Altogether number of dynamically generated ddls+textboxes are equal or less than 6. What i want to do is when user selects an item from a ddl or enters a value to a texbox, the value in that particular element(string) should be shown in 'ItemName' textbox. User can go on adding like that. Each added value(string) should be shown separated by a space in 'ItemName' textbox.
Futher every ddl and textbox(only dynamically generated ones-Field0, Field1, Field2, Field3, Field4, Field5, ) should get enabled one by one(one after another) allowing user to select(ddls)/enter(textboxes). But im struggling to develop the correct jquery function for this whole scenario. Pls help me with this. Thanks!
I have looked at other SO topics on this and they end up being either really old or using WebForms. I have an MVC view in which I have two listboxes. I want to move items back and forth between the two listboxes. The View is:
#using (Html.BeginForm())
{
#Html.ListBoxFor(m => m.SelectedAttributes, Model.Attributes, new {id="listBoxAvail", SIZE = 5} )
<input type="submit" name="add"
id="add" value="MoveRight" />
<input type="submit" name="remove"
id="remove" value="MoveLeft" />
#Html.ListBoxFor(m => m.SelectedAttributes2, Model.SelectedItems, new { id = "listBoxSel", SIZE = 5})
}
The ViewModel is:
public class OptInViewModel
{
public IEnumerable<string> SelectedAttributes { get; set; }
public IEnumerable<string> SelectedAttributes2 { get; set; }
public IEnumerable<SelectListItem> Attributes { get; set; }
public IEnumerable<SelectListItem> SelectedItems { get; set; }
}
And the Controller code is:
public ActionResult Index()
{
AttributeEntities db = new AttributeEntities();
List<SelectListItem> listSelectListItems = new List<SelectListItem>();
List<SelectListItem> listSelItems = new List<SelectListItem>();
foreach (var attributes in db.HarmonyAttributes)
{
SelectListItem selectList = new SelectListItem
{
Text = attributes.AttributeName,
Value = attributes.AtrributeLabel,
Selected = false
};
listSelectListItems.Add(selectList);
}
foreach (var sel in db.SelectedHarmonyAttributes)
{
SelectListItem selList = new SelectListItem
{
Text = sel.CustomLabel,
Value = sel.HarmonyAttribute_ID.ToString(),
Selected = false
};
listSelectListItems.Add(selList);
}
OptInViewModel viewModel = new OptInViewModel
{
Attributes = listSelectListItems,
SelectedItems = listSelItems
};
return View(viewModel);
}
I used JQuery to try to do this but it's not working (nothing gets transferred to 2nd listbox). Anyone kinow what's wrong?
<script src="~/Scripts/jquery-2.1.1.js"></script>
<script>
$(function () {
$("add").click(function () {
$("#listBoxAvail > option:selected").each(function () {
$(this).remove().appendTo("#listBoxSel");
});
});
$("remove").click(function () {
$("#listBoxSel > option:selected").each(function () {
$(this).remove().appendTo("#listBoxAvail");
});
});
});
</script>
Replace buttons type from submit to to button like below
<input type="button" name="add" id="add" value="MoveRight" />
<input type="button" name="remove" id="remove" value="MoveLeft" />
In your JavaScript correct selectors prepend # to ids, it should work!
$("add") to $("#add")
and
$("remove") to $("#remove")
If you want you can reduce it to
<script>
$(function() {
$(document)
.on("click", "#add", function() {
$("#listBoxAvail :selected").remove().appendTo("#listBoxSel");
})
.on("click","#remove", function() {
$("#listBoxSel :selected").remove().appendTo("#listBoxAvail");
});
});
</script>
You can use the jQuery-Dual-Listbox plugin for jQuery. It requires a bit of setup but then works well enough in the MVC environment. One caveat is that in order for your selected values in the 2nd listbox to be posted back to the server for processing, you need to ensure that all items in that listbox are selected before the form gets submitted.
e.g. for your markup:
<script src="jQuery.dualListBox-1.3.js" type="text/javascript"/>
<script type="text/javascript">
$(function () {
$.configureBoxes({
box1View: 'listBoxAvail',
box2View: 'listBoxSel',
to1: 'remove',
to2: 'add',
allTo1: 'remove-all', //you must create this button
allTo2: 'add-all', //you must create this button
useFilters: false
});
});
$("#listBoxSel").closest("form").on("submit",
function() {
//only selected options in listbox get POSTed back!
$("#listBoxSel > option").prop("selected", true);
return true;
}
}
</script>
Source
I have a two cascading dropdown, when I run the application everything works fine, because the cascade works, but when I get the value of the dropdown only get the value of first dropdown. The second I always get the value of zero.
The ViewModel code:
public class MyViewModel
{
public string SelectedUniversidadId { get; set; }
public string SelectedCiudadId { get; set; }
public IEnumerable<UNIVERSIDAD> Universidades { get; set; }
}
Partial view code:
<script type="text/javascript">
$(function () {
$('#universidad').change(function () {
var selectedUniversidadId = $(this).val();
$.getJSON('#Url.Action("GetCiudadList", "Consultorio", new { Area = "Superusuario", controller = "Consultorio" })', { UniversidadId: selectedUniversidadId }, function (myData) {
var citiesSelect = $('#ciudad');
citiesSelect.empty();
$.each(myData, function (index, itemData) {
citiesSelect.append($('<option/>', {
value: itemData.Value,
text: itemData.Text
}));
});
});
});
});
</script>
#model RolesMVC3.Areas.Superusuario.Models.MyViewModel
<div>
Universidad:
#Html.DropDownListFor(x => x.SelectedUniversidadId, new SelectList(ViewBag.IdUniversidad, "IdUniversidad", "Nombre"), "-- Selecione Universidad --", new { id = "universidad" })
</div>
<div>
Ciudad:
#Html.DropDownListFor(x => x.SelectedCiudadId, Enumerable.Empty<SelectListItem>(), "-- Seleccione Ciudad --", new { id = "ciudad" })
</div>
Controller code:
public ActionResult GetCiudadList(int UniversidadId)
{
decimal idd = (decimal)UniversidadId;
var universidades = (from u in db.UNIVERSIDAD
join s in db.SEDE_UNIVERSIDAD on u.IdUniversidad equals s.IdUniversidad
join c in db.CIUDAD on s.IdCiudadSede equals c.IdCiudad
where u.IdUniversidad == idd
select c).ToList();
var myData = universidades.Select(a => new
{
Text = a.NombreCiudad,
Value = a.IdCiudad.ToString(),
});
return Json(myData, JsonRequestBehavior.AllowGet);
Thanks and blessings
You need a controller action that receives 2 parameters (selected values for the 2 dropdowns). Also, pay attention to the values of the name attributes for the input elements. the name of the parameters need to be the same as the "name" input attribute.