I use in my Razor View the following ViewModel.
public class EditionStatusReservation
{
public Reservation Reservation { get; set; }
[Display(Name = "Status:")]
public IEnumerable<SelectListItem> States { get; set; }
}
The class Reservation looks like this:
public class Reservation
{
[Display(Name = "Status:")]
[Required]
[MinLength(3), MaxLength(15)]
public string Status { get; set; }
}
In my Razor view when I click submit button I would like to assign to variable Status new value using javascript. So far I created something like this.
$(function () {
$("form").submit(function () {
var selTypeText = $('select[name="SelectReservationState"]').val();
$("#Reservation.Status").val(selTypeText);
});
});
This solution is not proper. How can I access to field named Status to set its value?
Section with dropdownlist where item to assign is taken.
<div class="form-group">
#Html.LabelFor(model => model.States, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("SelectReservationState", Model.States, new { id = "SelectReservationState" })
</div>
</div>
Related
I am build my first .NET Core MVC application and using the Entity Framework. I have a edit page where users are allowed to enter the Quantity that they would like to order. The model classes are like below
public partial class Inventory
{
public string Name { get; set; }
public int QuantityAvailable { get; set; }
public string RoomNumber { get; set; }
public int InventoryId { get; set; }
[NotMapped]
public int? QuantityReq { get; set; }
}
and
public class Item
{
public int CustomId { get; set; }
public Inventory Inventory { get; set; }
}
The QuantityReq doesnot exists in the DB so I added them as NotMapped. So I have a view name is AddtoOrder on the Item like
#model JAXSurplusMouseApp.Models.Item
#{
ViewData["Title"] = "Edit";
}
<h4>Add to Order</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="AddtoOrder">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="#Model.Inventory.Name" class="control-label"></label>
<input asp-for="#Model.Inventory.Name" class="form-control" readonly />
</div>
<div class="form-group">
<label asp-for="#Model.Inventory.QuantityAvailable" class="control-label"></label>
<input asp-for="#Model.Inventory.QuantityAvailable" class="form-control" readonly />
</div>
<div class="form-group">
<label asp-for="#Model.Inventory.RoomNumber" class="control-label"></label>
<input asp-for="#Model.Inventory.RoomNumber" class="form-control" readonly />
</div>
</form>
<form method="post"
asp-controller="Inventories"
asp-action="OrderItem">
<label class="control-label">Quantity Required</label>
<input type="text" id="quantityReq" name="quantityReq" value=#Model.Inventory.QuantityReq />
<input type="hidden" id="customerID" name="customerID" value="#Model.CustomId" />
<input type="hidden" id="invetoryID" name="invetoryID" value="#Model.Inventory.InventoryId" />
<button type="submit"><u>Order</u></button>
</form>
</div>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
The Controller action is like below, if the user entering the quantity is more than the Quantity that is available then the order is placed and it navigates back to the other page. But if users enter a number in the Quantity required that is more than the Quantity Available then I need to post a error message in the same page that they have entered invalid quantity
// Action to launch the AddtoOrder page
public async Task<IActionResult> AddtoOrder(int? inventoryID, int? custID)
{
if (inventoryID == null || custID == null)
{
return NotFound();
}
Customer custData = await _context.Customers.FindAsync(custID);
var inventories = await _context.Inventories.FindAsync(inventoryID);
var model = new Item
{
CustomId = (int)custID,
Inventory = inventories
};
return View(model);
}
//Action athat allows the users to submit the order
public async Task<IActionResult> OrderItem(int? customerID, int? invetoryID, int quantityReq)
{
if (customerID == null || invetoryID == null)
{
return NotFound();
}
Customer custData = await _context.Customers.FindAsync(customerID);
var intData = await _context.Inventories.FindAsync(invetoryID);
if (quantityReq <= intData.QuantityAvailable && quantityReq > 0)
{
InventoryOrder io = new InventoryOrder();
io.OrderQuantity = quantityReq;
io.InventoryId = (int)invetoryID;
_context.Add(io);
await _context.SaveChangesAsync();
intData.QuantityAvailable = intData.QuantityAvailable - quantityReq;
_context.Update(intData);
await _context.SaveChangesAsync();
return RedirectToAction("Index", "Inventories", new { id = customerID });
}
else if (quantityReq > intData.QuantityAvailable){
How to redirect to the same page back with the validation error
}
}
first of all you should add #Html.ValidationSummary(false, "", new { #class = "error" }) to your form. Also, I would recommend you use HTML Helpers.
This is simple example of form:
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
#Html.LabelFor(m => m.Name)
#Html.TextBoxFor(m => m.Name)
#Html.LabelFor(m => m.Age)
#Html.TextBoxFor(m => m.Age)
<input type="submit" value="Submit"/>
#Html.ValidationSummary(false, "", new { #class = "error" })
}
And then you can custom validate your model and send error to View:
// Validation logic
else if (quantityReq > intData.QuantityAvailable)
{
ModelState.AddModelError("QuantityReq", "QuantityReq more than QuantityAvailable");
return View();
}
I know that this question might have been already on this site, but there are some different things in my approach because I use #Html.EditFor and #Html.DropDownList.
So I have a drop down list and when I choose the ID there I want to retrieve some information from the DB then populate some fields in the current form. I know that I should use JS but I don't know how.
View:
#model TestApp.Dtos.InsertDto
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="col-md-9">
#Html.DropDownListFor(model => model.Category, new SelectList(Model.ListOfCategory, "Text", "Text"), "-- Please select --", htmlAttributes: new { #class = "form-control"});
</div>
<div class="col-md-9">
#Html.EditFor(model => model.Car, new{htmlAttributes = new { #class = "form-control" }});
</div>
#*And then the form continues with other fields and after that the submit button *#
}
You can use ajax to get data from backend,and put the result data into somewhere you want.Here is a simple demo to get a selectListItem from backend and put it into a div.If you want to do something more complex,you need to share the structure of InsertDto,and explain clearly what kind of data you will get from db and explain what does populate some fields in the current form mean?
View:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="col-md-9">
#Html.DropDownListFor(model => model.Category, new SelectList(Model.ListOfCategory, "Text", "Text"), "-- Please select --", htmlAttributes: new { #class = "form-control" ,#onchange = "getData()" })
</div>
<div id="dbdata">
</div>
}
js:
<script>
function getData() {
$.ajax({
type: "POST",
data: { Category: $("#Category").val() },
url: '/B/GetData',
}).done(function (result) {
$("#dbdata").html("the selected value is " + result.text);
});
}
</script>
Model:
public class InsertDto
{
public string Category { get; set; }
public List<SelectListItem> ListOfCategory { get; set; }
}
controller:
public IActionResult Index(string id)
{
InsertDto i = new InsertDto { ListOfCategory = new List<SelectListItem> { new SelectListItem { Text = "t1" }, new SelectListItem { Text = "t2" }, new SelectListItem { Text = "t3" } } };
return View(i);
}
public SelectListItem GetData(string Category)
{
return new SelectListItem { Text = Category, Value = Category + "value" };
}
result:
I am trying to use jquery unobtrusive validation in my form, and no matter if the html inputs are empty or not, the validation message is always showing as soon as I open the page. The HTML is in a handlebars template. I am using HttpPost to retrieve data when loading the page.
My View:
<form id="submitForm" class="form">
<section id="conferenceContainer"></section>
<div id="saveBtnContainer">
<input type="submit" id="saveBtn" class="btn" value="Submit" />
<div id="lblCheckContainer">
<label id="lblCheck"></label>
</div>
</div>
</form>
<script type="text/x-handlebars-template" id="conferenceTemplate">
<div id="newConference">
<div class="form-group row">
#Html.LabelFor(x => x.ConferenceTitle,
new { #class="confLabels" })
#Html.TextBoxFor(x => x.ConferenceTitle,
new { #id="confTitle", #class="form-control", #Value= "{{ConferenceTitle}}" })
#Html.ValidationMessageFor(x => x.ConferenceTitle, "*Enter a conference title*", new { #class="text-danger" })
</div>
<div class="form-group row">
#Html.LabelFor(x => x.EventDate,
new { #class="confLabels" })
#Html.TextBoxFor(x => x.EventDate,
new { #id="confDate", #class="form-control", #Value="{{formatDate EventDate}}" })
#Html.ValidationMessageFor(x => x.EventDate, "*Enter the date of the conference*", new { #class="text-danger" })
</div>
<div class="form-group row">
#Html.LabelFor(x => x.RegFullPrice,
new { #class="confLabels" })
#Html.TextBoxFor(x => x.RegFullPrice,
new { #id="confPrice", #class="form-control", #Value="{{RegFullPrice}}" })
#Html.ValidationMessageFor(x => x.RegFullPrice, "*Enter the price to register for conference*", new { #class="text-danger" })
</div>
<div class="form-group row">
#Html.LabelFor(x => x.PreRegEndDate,
new { #class="confLabels" })
#Html.TextBoxFor(x => x.PreRegEndDate,
new { #id= "confPreRegDate", #class="form-control", #Value= "{{formatDate PreRegEndDate}}" })
#Html.ValidationMessageFor(x => x.PreRegEndDate, "*Enter the last day to pre-register for conference*", new { #class="text-danger" })
</div>
<div class="form-group row">
#Html.LabelFor(x => x.PreRegDiscount,
new { #class="confLabels" })
#Html.TextBoxFor(x => x.PreRegDiscount,
new { #id= "confPreRegDiscount", #class="form-control", #Value= "{{PreRegDiscount}}" })
#Html.ValidationMessageFor(x => x.PreRegDiscount, "*Enter the discount for pre-registration*", new { #class = "text-danger" })
</div>
</div>
</script>
I am handling the submit input in .ready function where 'saveData()' is a method with the ajax call.
<script type="text/javascript">
var setup = new ConferenceSetup();
$(document).ready(function () {
setup.GetData();
$('#submitForm').submit(function () {
var confirmSave = confirm("Are you finished editing the Conference?");
if (confirmSave) {
setup.SaveData();
event.preventDefault();
} else {
event.preventDefault();
}
});
});
</script>
It seems I have the server side validation working but I cannot get the client side to act like I want.
My model:
[DisplayName("Conference Title")]
[Required]
public string ConferenceTitle { get; set; }
[DisplayName("Event Date")]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd", ApplyFormatInEditMode = true)]
[Required]
public DateTime EventDate { get; set; }
[DisplayName("Registration Price")]
[Range(0, 999.99, ErrorMessage = "Price must be between $0 and $1,000")]
[Required]
public decimal RegFullPrice { get; set; }
[DisplayName("Pre-Registration End Date")]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd", ApplyFormatInEditMode = true)]
[Required]
public DateTime PreRegEndDate { get; set; }
[DisplayName("Pre-Registration Discount")]
[Range(0, 999.99, ErrorMessage = "Discount must be between $0 and $1,000")]
[Required]
public decimal PreRegDiscount { get; set; }
My Controller:
[Authorize]
public class ConfSetupController : Controller
{
public ActionResult NewConf()
{
ConferenceModel model = new ConferenceModel();
return View(model);
}
This is what my page looks like, the validation messages never go away
Any help or suggestions is greatly appreciated!
To hide the validation on page load check if .field-validation-error and .validation-summary-valid css class "display" property is set to "none".
When I am saving my data for the first time (when clicked on save button of my view) then I am getting value of submitButton variable in my controller action. But when I am editing my view and then click on save then I am getting null value in submitButton variable in my controller action.
My View Model
public class TermiViewModel : ViewModelBase
{
public long Id { get; set; }
public string Name { get; set; }
}
My View
#model TermiViewModel
#using (Html.BeginForm("MyActionMethod", "MyController", FormMethod.Post))
{
#Html.HiddenFor(model => model.Id)
<div>
#Html.LabelFor(model => model.Name)
#Html.EditorFor(model => model.Name)
</div>
<button name="submitButton" value="Save" type="submit"
onclick="return JavaScriptFunction();">Save</button>
<button name="submitButton" value="Cancel" type="submit"
onclick="return JavaScriptFunction();">Cancel</button>
}
Below is the Javascript I am using in my view.
<script language="javascript" type="text/javascript">
function JavaScriptFunction() {
return true;
}
</script>
Below is my Controller class.
public class MyController : CoreMvcController
{
private readonly ITermiRepositoryService _termiRepository;
public MyController(ITermiRepositoryService termiRepository)
{
_termiRepository = termiRepository;
}
}
Below is my action Method where I am getting values from my view.
[HttpPost]
public ActionResult MyActionMethod(TermiViewModel termiViewModel, string submitButton)
{
try
{
voucherViewModel =_termiRepository.Save(termiViewModel);
switch (submitButton)
{
case "Cancel":
return RedirectToAction("Edit",termiViewModel.Id);
default:
return RedirectToAction("Index");
}
}
catch (Exception exception)
{
}
return RedirectToAction("Index");
}
In my above Controller method I get the null value for my submitButton variable while editing my view. I don't understand why I am getting null value because while creating for the first time, I am getting values of submitButton from the submit button.
Thanks for any help!
For the solution, I need to change following classes:
My View Model:
// A new property "SaveButtonValue" added to my view model.
public class TermiViewModel : ViewModelBase
{
public long Id { get; set; }
public string Name { get; set; }
public string SaveButtonValue { get; set; }
}
My View:
// Added a hidden field for "SaveButtonValue" and passing this keyword in
// Javascript function for onclick of submit button.
#model TermiViewModel
#using (Html.BeginForm("MyActionMethod", "MyController", FormMethod.Post))
{
#Html.HiddenFor(model => model.Id)
#Html.HiddenFor(model => model.SaveButtonValue)
<div>
#Html.LabelFor(model => model.Name)
#Html.EditorFor(model => model.Name)
</div>
<button name="submitButton" value="Save" type="submit"
onclick="return JavaScriptFunction(this);">Save</button>
<button name="submitButton" value="Cancel" type="submit"
onclick="return JavaScriptFunction(this);">Cancel</button>
}
Javascript:
// Populating my property "SaveButtonValue" through javascript
<script language="javascript" type="text/javascript">
function JavaScriptFunction(submitButton)
{
if (objButton) {
$('#SaveButtonValue').val(submitButton.value);
}
return true;
}
</script>
My action method:
[HttpPost]
public ActionResult MyActionMethod(TermiViewModel termiViewModel)
{
try
{
voucherViewModel =_termiRepository.Save(termiViewModel);
switch (termiViewModel.SaveButtonValue)
{
case "Cancel":
return RedirectToAction("Edit",termiViewModel.Id);
default:
return RedirectToAction("Index");
}
}
catch (Exception exception)
{
}
return RedirectToAction("Index");
}
Newbie ALERT
Basically I have a web application that has a dropdown list. When you select an item in the drop-down list the table is drawn to show all the credentials that are tied to that drop-down option.
Problem: When running, everything functions properly except for the JavaScript piece that does not remove the line in the table, but deletes the record on the back-end. So once i refresh and go back to that credential type the one I deleted is gone.
I've tried a lot of different stuff, but i pretty new to JavaScript and C#, don't know if there is a better way of doing this. Probably supplied too much information but i rather too much than not enough! :)
Any help, tips, ideas are greatly appreciated.
Credential API Controller: Delete Function
[HttpDelete]
public IHttpActionResult DeleteCustomer(int id)
{
var credentialInDb = _context.Credentials.SingleOrDefault(c => c.Id == id);
if (credentialInDb == null)
return NotFound();
_context.Credentials.Remove(credentialInDb);
_context.SaveChanges();
return Ok();
}
Model for Credential
public class Credentials
{
public int Id { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
[Required]
[StringLength(255)]
public string Username { get; set; }
[Required]
[StringLength(255)]
public string Password { get; set; }
public string Website { get; set; }
public string Notes { get; set; }
public CredentialType CredentialType { get; set; }
[Display(Name = "Credential Type")]
public int CredentialTypeId { get; set; }
}
ViewModel for CredentialFormViewModel
This allows the selectedCredential variable for the page below
public class CredentialFormViewModel
{
public IEnumerable<CredentialType> CredentialTypes { get; set; }
public Credentials Credentials { get; set; }
public int SelectedCredentialTypeId { get; set; }
}
View that displays the DataTable:
#model Appp.ViewModels.CredentialFormViewModel
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Select a Credential Type</h2>
#Html.DropDownListFor(m => m.SelectedCredentialTypeId, new SelectList(Model.CredentialTypes, "Id", "Name"), "Select Credential Type", new { #class = "form-control", onchange = "SelectCredType()" })
<br/>
<table id="credentials" class="table table-bordered table-hover">
<thead>
<tr>
<th>Credential</th>
<th>Username</th>
<th>Password</th>
<th>Website</th>
<th></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
#section scripts
{
<script>
function SelectCredType() {
var credId = $('#SelectedCredentialTypeId').val();
if ($.fn.dataTable.isDataTable("#credentials")) {
if (credId == "") {
var table = $("#credentials").DataTable();
table.destroy();
} else {
var table = $("#credentials").DataTable();
table.destroy();
SelectCredType();
}
} else {
$(document)
.ready(function() {
var table = $("#credentials")
.DataTable({
ajax: {
url: "/api/credentials?credentialTypeId=" + credId,
dataSrc: ""
},
columns: [
{
data: "name",
},
{
data: "username"
},
{
data: "password"
},
{
data: "website"
},
{
data: "id",
render: function(data, type, credentials) {
return "<button class='btn btn-primary btn-xs js-delete' data-credential-id=" + credentials.id + ">Delete</button>";
}
}
]
});
}
);
}
};
$("#credentials")
.on("click",
".js-delete",
function() {
var button = $(this);
bootbox.confirm("Are you sure you want to delete this?",
function(result) {
if (result) {
$.ajax({
url: "/api/Credentials/" + button.attr("data-credential-id"),
method: "DELETE",
sucess: function() {
table.row(button.parents("tr")).remove().draw();
}
});
}
});
});
</script>
}
First issue
Your JavaScript code does not work because the table variable is undefined within your delete function.
There are many ways you could approach to fix that. But first you will need to get your head around variable scopes in JavaScript.
Your simplest solution is to make table a globally-scoped variable that way you can access the instance from any function you create. So instead of defining it here:
...
$(document)
.ready(function() {
var table = $("#credentials")
...
Move it up to the top of your script file:
var table;
function SelectCredType() {
...
$(document)
.ready(function() {
table = $("#credentials")
...
}
Now when you access it from your Delete function, it will be defined.
Note: I would also change the name of the table variable to something else as global variables in JavaScript will conflict with any script you import which can lead to a debugging nightmare. Best to name it something that will be most likely unique, eg. coberlinTable.
Second Issue
I don't know if you did a cut and past error, but you have misspelled success in your ajax Delete function.