Cascading dropdown with Static data - asp.net

i need to develop two dropdown list in my MVC3 project, where first dropdown will be a db driven and based on the data selected on first dropdown my second dropdown should change. Second dropdown is having hard coded text and value. how could i achived this. please help
Following is my codebased
viewmodel
public IEnumerable<SelectListItem> ProductTypeCode{ get; set; }
public int? ProductID { get; set; }
public IEnumerable<SelectListItem> ProductGroupCode;
public int? ProductGrpID { get; set; }
Controller
public ActionResult Index() {
var model = new MyViewModel
{
// TODO: Fetch those from your repository ,
model.ProductTypeCode= new SelectList(obj.ProductTypeCode as System.Collections.IEnumerable, "Value", "DispalyText");
return view(model);
}
VIEW
#Html.DropDownListFor(m => m.ProductID , Model.ProductTypeCode, "ALL" , new { #class = "DropDownList" })</td>
My question is based on the above dropdown of productType, i need to populate another dropdown called "ProductGroup" which is having hardcoded value. based on the ProductType dropdown the value of productgroup should change.

You have several options.
You can write your own javascript to handle the onchange event. There are literally thousands of simple tutorials on this exact topic. This one will probably address your question the best.
You can use extensions like Telerik's. They're relatively straight forward, well documented, but do have the extra weight of another library on them (although the markup they generate is pretty slim).
If you go with option 1 and write your own, the two main things you'll have to add in will be an extra controller action and some javascript.
The javascript will listen for change events on your product Id drop down. Put this in a document ready function on the page itself.
$("#ProductID").change(function() {
// Get the product id selected
var id = $(this).val();
// Fire off an ajax request to get the groups
$.ajax({
// whatever the url may be.
url: "#Url.Action("Groups")" + id, // Append the id to the url.
dataType: "json",
type: "POST",
error: function() {
alert("An error occurred.");
},
success: function(data) {
var items = "";
$.each(data, function(i, item) {
items += "<option value=\"" + item.Id+ "\">" + item.Name + "</option>";
});
// Set the secondary dropdown content to the newly created
// list of options. Use whatever Id your secondary is.
$("#ProductGroup").html(items);
});
The controller action responds to the ajax call with the list of appropriate product groups.
public class ProductsController : Controller
{
public ActionResult Groups(int id)
{
// You only need the id and a name field in the response, not the
// entire object.
var groups = _myService.FindGroupsForProductId(id)
.Select(g => new
{
Id = g.Id,
Name = g.Name
});
// Return a json result. You only need to re
return Json(groups);
}
}
The code above should help you get started. It's assuming several things that you didn't show in your code at all. Your question got downvoted because at first, you didn't post any code. Then, the code that you did post doesn't really show that you've put any effort into finding the solution on your own. Find some jquery tutorials on this, there are thousands, then if you have specific problems, bring them here.

Related

ASP .NET API Ajax How to update only some properties?

I have a datatable and for each row there's a button. When clicked, it should set a property (field AvailableToCall) in my class. So I call an Ajax for my update method API passing the value (true) for the property. The problem is that when I do that, all the other properties (for example, name, adress, etc.) are set to null. Is there a way that I can update only a specific property leaving all the other properties of my table the same as before the AJAX call?
$.ajax({
url: "/api/person/" + personId,
type: "put",
data: {
AvailableToCall: true
}
}).done(function () {
// something
}
Thanks for the help.
Another way you could achieve this is a different endpoint:
$.ajax({
url: "/api/person/" + personId + "/availabletocall",
type: "put",
data: true
}).done(function () {
// something
}
So your url is something like below which accepts a body with a boolean:
/api/person/123/availabletocall
Your controller action could simply receive that single value and update whichever datasource you're using.
First of all you need to show your ApiController method.
I assume your method is like this,
public HttpResponseMessage Put(int id)
{
var _AvailableToCall = HttpContext.Current.Request.Form["AvailableToCall"];
//I'm using HttpContext to fetch the data in the above line. You can fetch
//the bool value as your way
//Now you just need to fetch the data by personId, (here it is id).
myClass obj = contextObj.myClass().where(m=>m.personId ==
id).firstOrDefault();
obj.AvailableToCall = true;
//That's it. Now you can update it.
contextObj.Entry(obj).State = System.Data.Entity.EntityState.Modified;
contextObj.SaveChanges();
return Request.CreateResponse(HttpStatusCode.OK, new { Status = "OK",
Message = e.ToString() });
//You can return your data as your requirements or as you are writing in
//your project.
}
See here "contextObj" is the object of my Context Class. And "myClass" is my modal class that I want to update/save data.
You can write "Json" return type in place of "HttpResponseMessage".
Cheers...

Adding click binding to a Knockout.js array from Web API AJAX result

I have an ASP.NET Web API method that returns a list of products:
public async Task<IEnumerable<Product>> Get()
{
var products = new IEnumerable<Product>();
// Data populated here
return products;
}
This API call is used by a Knockout.js observableArray:
// Define viewmodel
var myViewModel = {
products = ko.observableArray([]);
};
// Apply knockout bindings
ko.applyBindings(vm);
// Function that obtains product data
function listProducts(viewmodel) {
var productsQuery = "api/products/get";
// Send an AJAX request
$.getJSON(productsQuery).done(viewmodel.products);
}
I would like to apply a click binding to these products, which would be a method named myClickFunction in this case. If possible, the method should be a function belonging to the objects that are returned by my Web API call :
<ul data-bind="foreach: products">
<li class="item" data-bind="text: productName, click: myClickFunction">
</li>
</ul>
Is it possible for me to add a function to the Web API result, which I can then use in the observableArray?
You should consider your Product items as DTO's, and use proper view models in your front end code that can be passed such a DTO. For example, let's assume this server side class (since you haven't shown yours):
public class Product
{
public string Name { get; set; }
public string Description { get; set; }
}
Then you could have a view model like this:
var ProductVm = function (dto) {
var self = this;
self.productName = dto.name;
self.description = dto.description;
self.myClickFunction = function() {
// Your function...
}
}
And pass them along these lines:
function listProducts(viewmodel) {
var productsQuery = "api/products/get";
// Send an AJAX request
$.getJSON(productsQuery).done(function (result) {
viewmodel.products(result.map(function (dto) { return new ProductVm(dto); }));
});
}
Additionally, you may want to look at streamlining this to taste using the mapping plugin or by plainly extending self with the dto.

Validating a field based on a different database table / entity

I am writing an MVC 4 application, and using Entity Framework 4.1. I have a validation question which I cannot seem to find the answer to.
Essentially, I have an Entity (object) called "Product" which contains a field "Name", which must follow strict naming conventions which are defined in a separate Entity called "NamingConvention". When the user enters a value, the system needs to check it against the rules established in the NamingConvention entity, and return an error if need be.
Where should this validation be done, and how? I need to check the NamingConvention entity when doing the validation, which means I would need a database context since I'm referencing a different entity. Is there any validation method which won't require me to create a new context? I was thinking of doing the validation in the Controller, since it already creates a data context, but this doesn't seem like the right place to do it.
Thanks for any help!
I have done things like this using a JQuery post (ajax) call from the webpage where the name is being entered. You then post (the value of name) to a method on your controller which can return a JSON value that contains a flag saying if the validation passed and also a message that you want to return to your user. For example :
Javascript in webpage :
$("#name").change(function () {
var nameVal = $(this).val();
$.post(getRoot() + "/NameController/ValidateName", { name: nameVal },
function (data) {
if (data.valid == "true") {
alert("A valid name was chosen");
} else
{
alert(data.message);
}
}, "json");
});
Controller (NameController) Code :
[HttpPost]
public ActionResult ValidateName(string name)
{
// actual validation carried out in a static utility class (Utils.IsNameValid)
// if you are loading the same validation rules from your table each time
// consider caching the data in the application cache or a static List.
bool nameIsValid = Utils.IsNameValid(name, out string ErrorMessage);
JsonResult result = new JsonResult();
result.Data = new { valid = (nameIsValid "true" : "false"), message = ErrorMessage };
return result;
}
I'm using EF 5 but believe you can use this method ... apologies in advance if I'm misleading you with this answer.
You could do the validation within your context (or a context decorator)
public override int SaveChanges()
{
var products = this.GetChangedProducts();
foreach (var product in products)
{
this.ValidateName(product);
}
return base.SaveChanges();
}
private IEnumerable<Product> GetChangedProducts()
{
return (
from entry in _context.ChangeTracker.Entries()
where entry.State != EntityState.Unchanged
select entry.Entity)
.OfType<Product>();
}
private void ValidateName(Product product)
{
//validate here
}

Updating View with Model changes via Ajax Post - MVC3

I am trying to use an Ajax (I think) call to update my model value and then have that new value reflected in the view. I am just using this for testing purposes for the moment.
Here's the overview:
MODEL
public class MyModel
{
public int Integer { get; set; }
public string Str { get; set; }
}
CONTROLLER
public ActionResult Index()
{
var m = new MyModel();
return View("Test1", m);
}
[HttpPost]
public ActionResult ChangeTheValue(MyModel model)
{
var m = new MyModel();
m.Str = model.Str;
m.Str = m.Str + " Changed! ";
m.Integer++;
return View("Test1", m);
}
VIEW
#model Test_Telerik_MVC.Models.MyModel
#using Test_Telerik_MVC.Models
#{
ViewBag.Title = "Test1";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>
Test1</h2>
#if (false)
{
<script src="~/Scripts/jquery-1.4.4.min.js" type="text/javascript"></script>
<script src="~/Scripts/jquery-ui.min.js" type="text/javascript"></script>
}
<h2>
ViewPage1
</h2>
<div>
<input type="button" onclick="changeButtonClicked()" id="changeButton" value="Click Me!" />
<input type="text" value="#Model.Str" class="txt" id="str" name="Str"/>
<div></div>
</div>
<script type="text/javascript">
function changeButtonClicked() {
var url = '#Url.Action("ChangeTheValue", "Test1")';
var data = '#Model';
$.post(url, data, function (view) {
$("#Str").value = '#Model.Str';
});
}
</script>
Basically the view renders a button with a textbox. My sole aim is to simply display the value of my model (Str property) in the textbox.
I have tried various combinations of the changeButtonClicked() function to no avail. Test1 is the name of my controller. What I don't understand is when I debug it, the controller action fires and sets my values correctly. If I place a breakpoint on the "#Model.Str" section of the input tag, it shows me that my #Model.Str is equal to Changed! which is correct. However, as soon as my success function fires in the javascript, the value reverts back to it's original value.
I can make it work by changing the input type to submit and wrapping it in a #Html.BeginForm() section but I am wondering if/how to do it like this? Or is a Submit the only way to accomplish it?
Thanks
First thing in the jQuery the proper way to set a value of an input is to use:
$("#Str").val(#Model.Str);
Next we'll look at the controller. In the POST action result you are returning the entire View in your AJAX call. That means all the HTML, script references, and JavaScript are being returned in your jQuery post request. Since all you are trying to update is the value of the input named Str, I would just return that value as JSON and nothing else.
[HttpPost]
public ActionResult ChangeTheValue(MyModel model)
{
var m = new MyModel();
m.Str = model.Str;
m.Str = m.Str + " Changed! ";
m.Integer++;
return Json(m.Str);
}
Next I would place your HTML inputs in a <form> so you can have jQuery serialize your model for you and then you can change your jQuery post code to be:
function changeButtonClicked() {
var url = '#Url.Action("ChangeTheValue", "Test1")';
$.post(url, $('form').serialize(), function (view) {
$("#Str").val(view);
});
}
All the serialization is doing is encoding the inputs in your form into a string and if everything is named properly ASP.NET will bind that back to your model.
If you need to have your route handle both AJAX calls and full requests you could use ASP.NET's IsAjaxRequest function to test the request and return different results depending on if the request is AJAX or not. You would do something like this in your controller:
[HttpPost]
public ActionResult ChangeTheValue(MyModel model)
{
var m = new MyModel();
m.Str = model.Str;
m.Str = m.Str + " Changed! ";
m.Integer++;
if (Request.IsAjaxRequest) {
return Json(m.Str);
}
else {
return View("Test1", m);
}
}
In the ActionResult above you are doing everything you did before, but now are testing the request type and if it's AJAX you return a JSON result of your string value. If the request was not from an AJAX call then the full View (HTML, scripts, etc) are returned to be displayed in the browser.
I hope this is helps you out and is what you were looking for.
You can update the view, just not the model. The model in a razor page is compiled on the server in order to render the view; you would need to recompile the razor page after every ajax request.
Only real option is to return json from server and manually update DOM/View.

Bind DropDownlists with JQuery in Asp.Net

I have 3 dropdownlists for Country,State and Metro.
I want to when user seclect Country then State dropdownlist fill Jquery and when select Sate then Metro dropdownlist fill(like cascading dropdownlist of ajax).These process i want to do with JQuery.
I am going to describe it in ASP.NET MVC, but the same can be achieved if you either write an ASP.NET web service or just put a few page methods in your code behind to do the same - you'll also need a JSON serializer, either a 3rd party solution or the one in WCF.
Using MVC, first, let's have three controller actions - one to display the page, countries will be static, and two to get the states and metros respectively:
public ActionResult Index()
{
ViewData["Countries"] = _countryRepository.GetList();
return View();
}
public ActionResult States(string countryCode)
{
var states = _stateRepository.GetList(countryCode);
return Json(states);
}
public ActionResult Metros(string countryCode, string state)
{
var metros = _metroRepository.GetList(countryCode, state);
return Json(metros);
}
In the view, you have three DropDownLists, one is bound to the ViewData["Countries"] object, say it's named Countries, you can get the states in jQuery with an Ajax call like this:
$('#Countries').change(function() {
var val = $(this).val();
$states = $('#States');
$.ajax({
url: '<%= Url.Action('States') %>',
dataType: 'json',
data: { countryCode: val },
success: function(states) {
$.each(states, function(i, state) {
$states.append('<option value="' + state.Abbr+ '">' + state.Name + '</option>');
});
},
error: function() {
alert('Failed to retrieve states.');
}
});
});
The Metros drop down would be filled analogically, passing both the country and state selection to the server and getting back a JSON object with an array of metro areas.
I left out the details of repository implementation, just fill up the result variable on the server with a collection of states/metro areas in some way. I also made an assumption that the State class would have two properties - Abbr (e.g., 'CA') and Name (e.g., California).
I hope that it helps you in any way, or at least directs you somehow towards the solution.

Resources