My JavaScript will not run. I've been struggling with this for a while (2 days) Here's my current setup:
Created a new MVC 4 project. I intend to try out some AJAX, so named it AjaxTest.
Added a model (Vehicle.cs) consisting of three classes OdometerInfo, VehicleMinInfo, and Vehicle. Here they are:
public class OdometerInfo
{
public virtual string VIN { get; set; }
public virtual int Odometer { get; set; }
}
public class VehicleMinInfo : OdometerInfo
{
public virtual Nullable<int> VehicleYear { get; set; }
public virtual string Make { get; set; }
public virtual string Model { get; set; }
}
public class Vehicle : VehicleMinInfo
{
// default constructor
public Vehicle()
{
VIN = "MyFakeVin";
Odometer = 0;
VehicleYear = 2012;
Make = "Porsche";
Model = "911";
}
public override string VIN { get; set; }
public override int Odometer { get; set; }
public override Nullable<int> VehicleYear { get; set; }
public override string Make { get; set; }
public override string Model { get; set; }
// other fields
}
Then I replaced the contents of the template Index.cshtml with:
#model AjaxTest.Models.VehicleMinInfo
#{
ViewBag.Title = "Index";
}
<h2>Enter your odometer reading</h2>
#using (Html.BeginForm("Odometer", "Home", FormMethod.Post))
{
<h4>For the following vehicle.</h4>
#Html.DisplayFor(model => model.VIN) <br />
#Html.DisplayFor(model => model.VehicleYear) <br />
#Html.DisplayFor(model => model.Make) <br />
#Html.DisplayFor(model => model.Model) <br />
<h1>Enter Odometer</h1>
#Html.DisplayNameFor(model => model.Odometer)
#Html.EditorFor(model => model.Odometer)
#Html.HiddenFor(model => model.VIN);
<input type="submit" value="Odometer reading is correct" id="OdometerForm" />
}
Then I made a strongly typed view (Odometer.cshtml):
#model AjaxTest.Models.OdometerInfo
#{
ViewBag.Title = "Odometer";
}
<h2>Odometer</h2>
Your odometer has been entered. It is
#Html.DisplayFor(model => model.Odometer)
. (
#Html.DisplayFor(model => model.VIN)
)
And added to the controller:
public ActionResult Index()
{
VehicleMinInfo OdomObj = new Vehicle();
return View(OdomObj);
}
[HttpPost]
public ActionResult Odometer(OdometerInfo oi)
{
return View(oi);
}
All of that works. I can fill in an odometer reading and both the odometer and the VIN are passed back to the controller and displayed on the Odometer page. Now, it's time to start adding some JavaScript. So I created OdometerList.js with the eventual goal of passing back a list of odometer readings instead of just one, and in it I placed:
$("#OdometerForm").click(function () {
alert("Hello world!");
});
window.onload = function () {
if (window.jQuery) {
// jQuery is loaded
alert("Yeah!");
} else {
// jQuery is not loaded
alert("Doesn't Work");
}
}
$(document).ready(function () {
alert("!!!");
});
Then I added in _Layout.cshtml
#Scripts.Render("~/Scripts/jquery-1.3.2.min.js")
#Scripts.Render("~/Scripts/OdometerList.js")
And I double checked Web.config to be sure compilation debug was true:
<system.web>
<compilation debug="true" targetFramework="4.5" />
...
None of my alerts are triggered, not one. Is my setup wrong? I moved my JavaScript from OdometerList.js to the bottom of Odometer.cshtml and put it all between script tags, but there was no change. I am new to JavaScript, so have I made a mistake there?
This is really stumping me. Any help you can give will be much appreciated!
The version of jQuery had been updated. Once I put the correct version number in, I was able to use #Scripts.Render("~/Scripts/jquery-1.8.2.min.js") and everything works!
Related
Banging my head against a brick wall here. I have a Datatable that is populated by GET call to an api from a dropdown box. Ideally i want the user to select an option in the dropdown and the table will reload with the data from the call.
The api is getting called and data is being returned with each selection but the table doesnt display the data or get refreshed like i would expect.
CheckIn.cshtml
#model IEnumerable<Vidly.Models.Customer>
#{
ViewBag.Title = "CheckIn";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>CheckIn</h2>
<div class="form-group">
#Html.DropDownList("Customers",
new SelectList(Model, "Id", "Name"), "Please select a customer",
new { #class = "form-control", #id = "customers"})
</div>
<table id="rentals" class="table table-bordered table-hover">
<thead>
<tr>
<th>Id</th>
</tr>
</thead>
<tbody></tbody>
</table>
#section scripts
{
<script>
$(document).ready(function () {
var customerId;
var table = $("#rentals").DataTable({
ajax: {
type: 'GET',
url: '/api/RentalsApi/',
data: function (d) {
d.id = customerId ? customerId : -1;
},
dataSrc: ""
},
columns: [
{
data: "name"
}
]
});
$('#customers').on('change', function (e) {
console.log(this.value);
customerId = this.value;
table.ajax.reload();
});
});
</script>
}
API
// GET /api/RentalsApi/{1}
[HttpGet]
public IHttpActionResult GetRental(int id)
{
if (id == -1) return Json(new System.Web.Mvc.EmptyResult());
var customer = _context.Customers.SingleOrDefault(c => c.Id == id);
return Ok(customer);
}
Customer Model
using System;
using System.ComponentModel.DataAnnotations;
namespace Vidly.Models
{
public class Customer
{
public int Id { get; set; }
[Required(ErrorMessage = "Please enter customer's name.")]
[StringLength(255)]
public string Name { get; set; }
public bool IsSubscribedToNewsletter { get; set; }
public MembershipType MembershipType { get; set; }
[Display(Name = "Membership Type")]
public byte MembershipTypeId { get; set; }
[Display(Name = "Date of Birth")]
[Min18YearsIfAMember]
public DateTime? Birthdate { get; set; }
}
}
Just make your ajax api call as normal and then use this to redraw the table
table=$("#rentals").DataTable()
table.clear().rows.add(newData).draw(); //newData is the data you get from your ajax call
I have a view inside which there are two checkboxes. On checked I need to save currently assigned value into database table.
Here is the model:
public class RoomHk
{
public int RoomHkId { get; set; }
public int RoomId { get; set; }
public DateTime? DeepCleaning { get; set; }
public DateTime? NewLinen { get; set; }
}
This is the child table of my Room Table. Following is my view, suppose user check on first checkbox then he clicks on save button, then I want to save current datetime in the NewLinen column of the RoomHk table to that respective RoomId. How can I do it with jQuery post method?
<div class="col-6">
#if (item.NewLinen == null)
{
<input type="checkbox" data-nlid="#item.RoomId" class="form-check-input newLinen" />
<label>New Linen</label>
<br />
}
#if (item.DeepCleaning == null)
{
<input type="checkbox" data-dcid="#item.RoomId" class="form-check-input deepClean" />
<label>Deep Cleaning</label>
}
</div>
<button type="button" class="btn btn-default insert" data-rid="#item.RoomId">Save</button>
$(function () {
$('.insert').click(function () {
$.post("#Url.Action("SetCleaningStatus", "HouseKeeping")", { id: $(this).data("id"), });
});
});
You could use Html.BeginForm and place the submit button inside the form. This is important, otherwise you'll need to employ additional scripts to get it working.
If you need to post the state of the two checkboxes (DeepCleaning and NewLinen) I'd suggest having them as Boolean instead of DateTime so you can have their states (checked/unchecked) mapped to the respective properties, because you seem to want to do that.
SetCleaningStatus.cshtml
#model RoomHk;
#Html.BeginForm("SetCleaningStatus", "HouseKeeping")
{
<!-- Will be posted to the controller, no additional Javascript necessary -->
#Html.HiddenFor(m => m.RoomId)
<div class="col-6">
#if (item.NewLinen == null)
{
<input type="checkbox" data-nlid="#item.RoomId" class="form-check-input newLinen" />
<label>New Linen</label>
<br />
}
#if (item.DeepCleaning == null)
{
<input type="checkbox" data-dcid="#item.RoomId" class="form-check-input deepClean" />
<label>Deep Cleaning</label>
}
</div>
<!-- IMPORTANT: the type needs to be `submit` instead of `button` -->
<input type="submit" class="btn btn-default insert" value="Save" />
}
HouseKeeping.cs
public class RoomHk
{
public int RoomHkId { get; set; }
public int RoomId { get; set; }
public DateTime? DeepCleaning { get; set; }
public DateTime? NewLinen { get; set; }
}
[HttpGet]
public ActionResult SetCleaningStatus()
{
var model = new RoomHk();
return View(model);
}
[HttpPost]
public ActionResult SetCleaningStatus(RoomHk arg)
{
bool response = new {
success = true
};
// Here is your RoomId
arg.RoomId;
arg.NewLinen = DateTime.Now;
// Save posted data to DB
// ...
// Return your response here
return Json(response);
}
POSTting the checked state of checkboxes
Use Html.CheckBoxFor and Html.LabelFor and let the compiler render those fields for you, with the right IDs and names properly set.
public class RoomHk
{
// Make them booleans
public bool DeepCleaning { get; set; }
public bool NewLinen { get; set; }
}
<div class="col-6">
<!--
<input type="checkbox" data-nlid="#item.RoomId" class="form-check-input newLinen" />
<label>New Linen</label>
<br />
-->
#Html.LabelFor(m => m.NewLinen, "New Linen")
#Html.CheckBoxFor(m => m.NewLinen, new { #class = "form-check-input" })
</div>
I can't seem to get the Validation error messages to show under the input model fields on the View.
The [Required] tag above Description input makes the ModelState Invalid, but doesn't stop the submission. I have to catch it with checking the Model State. Am I missing some .js files? I dont' have any examples to doublecheck this.
Here is my model (notice I have only one [Required] for now):
public partial class Requests
{
public int RequestID { get; set; }
public string NickName { get; set; }
public Nullable<double> Lat { get; set; }
public Nullable<double> Lng { get; set; }
public string ZipCode { get; set; }
[Required(ErrorMessage = "Description of what you need is missing.")]
public string Description { get; set; }
public System.DateTime DateCreated { get; set; }
}
Here is my View where the Description input needs input.
<div class="form-group">
#Html.LabelFor(model => model.Description, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextAreaFor(model => model.Description, new { htmlAttributes = new { #class = "form-control", #rows = "20", #cols = "200" } })
#Html.ValidationMessageFor(model => model.Description, "", new { #class = "text-danger" })
</div>
</div>
Here is my controller ActionResult (skinnied down)
if (ModelState.IsValid)
{
//THIS ALL WORKS IF Description HAS INPUT
}
else
{
TempData["Saved"] = "Nothing saved yet. Look for reason.";
return RedirectToAction("StoreRequests", new { lat = requests.Lat, lng = requests.Lng });
}
On ModelState failure the user is directed to the correct View and TempData shows that nothing was saved. However, there is no error message on the View below the offending input, no ValidationSummary at the top of the view, and submission is not stopped on input mistake.
#if(TempData["Saved"] != null)
{
<span style="color: red;">#TempData["Saved"].ToString()</span>
}
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
In order to get client side validation (and therefore prevent the form being submitted if its invalid), you need to include the following scripts in you view (or layout).
jquery-{version}.js
jquery.validate.js
jquer.validate.unobtrusive.js
If you have the default bundles set up by VS when you create a new project, you can simply add the following to the view
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
In addition, you should not be redirecting if ModelState is invalid, but rather returning the current view, which will display any validation errors even if the user has disabled javascript. By redirecting, your lose current ModelState so no validation errors will be displayed in the view your redirecting to, not to mention that any data the user previously filled (except the 2 parameters your passing) will be lost.
public ActionResult Edit (Requests model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// save you data and redirect
}
Include the following necessary scripts directly in your .cshtml file.
<script src="/Scripts/jquery.unobtrusive-ajax.js"></script>
<script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>
I have JS function that is basically
<script type="text/javascript">
function doSomething() {
var s = 'some data'
return s; }
</script>
and
#using (Html.BeginForm(new { data_to_send = x))
{
//some form controls that are sent to controller via model
}
Is it possible, and how, to assign value returned by doSomething function to x variable in form?
I don't need x in my model, because it won't go to database. It's just some additional info from user, how to manipulate data in model before saving to database.
edit: Controller action is
public actionresult MyController(string data_to_Send, model) {}
In the View:
#using (Html.BeginForm())
{
#Html.HiddenFor(model => model.X1)
#Html.HiddenFor(model => model.X2)
}
In the Model:
public class YourModel
{
public string X1 { get; set; }
public string X2 { get; set; }
}
In the Controller:
[HttpPost]
public ActionResult Index(YourModel model)
{
string x1 = model.X1;
string x2 = model.X2;
return View(model);
}
The form has to be posted in order to do what you are looking for.
You can post the model along with PostedDateValue
#using (Html.BeginForm("ActionMethod", "Controller", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-field required">
<label for="Posted Data">Posted Data</label>
<input id="txtPostedData" name="PostedDateValue" >
<input type="submit" class="gradient" value="SUBMIT" />
</div>
}
)
Controller
public ActionResult ActionMethod(string PostedDateValue)
{
}
Imagine below MVC parent model:
Model:
Namespace MyProject.SampleModel
{
public class ViewModelExample {
public FirstModel BoolValues { get; set; }
public SecondModel NamesValues { get; set; }
}
}
Namespace MyProject.SampleModel
{
public class FirstModel
{
public bool MyBoolean1 { get; set; }
public bool MyBoolean2 { get; set; }
}
public class SecondModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
View:
#model MyProject.SampleModel.ViewModelExample
#using (Html.BeginForm("MyAction", "MyController", FormMethod.Post, htmlAttributes: new { id = "Myform" }))
{
(...)
#Html.CheckBoxFor(m => m.BoolValues.MyBoolean1)
(...)
<input id="submitButton" type="button" value="Add" onclick="InitiateSequence();" />
(...)
}
<script type="text/javascript" src="~/Scripts/jquery-1.7.1.min.js"></script>
<script type="text/javascript">
(...)
function InitiateSequence()
{
// Do some stuff
}
(...)
function ScriptSample() {
if(#(Model.BoolValues.MyBoolean1 ? "true" : "false")
{
// It's true, do some stuff
}
else
{
// It's false, do some stuff
}
}
</script>
Controller:
public ActionResult MyAction(ViewModelExample model)
{
model.FirstModel = new TestsModel(); // I do not instantiate SecondModel as in the view for this controller i do not use it
return View(model);
}
Page is loading correctly, but when I click on the button it says javascript function InitiateSequence is not defined.... what's happening?
That could be because most possibly the function appears where it is not supposed to be. Also don't use inline attributes to bind the handlers, use event binding instead of inline handler.
<input id="submitButton" type="button" value="Add" />
and
<script type="text/javascript">
(...) //whatever code
$(function(){
$('#submitButton').on('click', InitiateSequence);
});