I have a View page which contains a dropdownlist of values populated from a custom constructor class.
The DDL is populated with a SelectList created from a list of custom items as follows:
public class CustomerType
{
public int Id { get; set; }
public string Name { get; set; }
public string ValidationRule { get; set; }
}
In my View I then set this as so:
#Html.DropDownListFor(model => model.Id, (IEnumerable) Model.SelectListOfCustomItems, "Please select...")
What I want to try and do is display the ValidationRule property for each item selected, and show this in a Label.
I figure I have to use JavaScript to do this, but I'm unsure how to actually get that ValidationRule property? I could probably get the selected item using code similar to the below, but I can't see how to drill down to get other data?
var dropDown = document.getElementById("MyDropDownListName");
dropDown.onchange = function () { DisplayValidationRule(this); };
function DisplayValidationRule(ddl)
{
document.getElementById('lblRule').textContent = [Unknown]
}
The bit I'm missing is where I've marked it [Unknown], as I don't have a club how to get this. I was thinking maybe something like ddl.items[ddl.selectedItem].value['ValidationRule'] but that doesn't work for me.
There are many ways to implement it. One way is to generate a set of hidden input fields like id="_CustomerType_id_xxx" with value "ValidationRule", then according to the select result to take the value. Another way is to send ajax request to get the rule. But I think it's not a good way.
Update
OK, below is my full codes, it passed on MVC4.
HomeController
public class HomeController : Controller
{
public ActionResult Index()
{
IList<CustomerType> customerTypes = new List<CustomerType>();
customerTypes.Add(new CustomerType { Id = 1, Name = "Customer Type 1", ValidationRule = "Rule 1" });
customerTypes.Add(new CustomerType { Id = 2, Name = "Customer Type 2", ValidationRule = "Rule 2" });
customerTypes.Add(new CustomerType { Id = 3, Name = "Customer Type 3", ValidationRule = "Rule 3" });
IEnumerable<SelectListItem> selectList =
from c in customerTypes
select new SelectListItem
{
Text = c.Name,
Value = c.Id.ToString()
};
return View(new CustomerVO { SelectListOfCustomItems = selectList, CustomerTypes = customerTypes });
}
}
Index.cshtml
#model MvcApplication1.Models.CustomerVO
#Html.DropDownListFor(model => model.CustomerTypeId, Model.SelectListOfCustomItems, "Please select...")
#foreach (var customerType in Model.CustomerTypes)
{
<input type="hidden" id="_customerType_#customerType.Id" value="#customerType.ValidationRule" />
}
<label id="lblRule"></label>
#section scripts
{
<script>
$(document).ready(function () {
var dropDown = document.getElementById("CustomerTypeId");
dropDown.onchange = function () { DisplayValidationRule(this); };
function DisplayValidationRule(ddl)
{
document.getElementById('lblRule').textContent = $("#_customerType_" + ddl.value).val();
}
});
</script>
}
Related
I have two related models.
public partial class bs_delivery_type
{
public decimal delivery_id { get; set; }
public decimal delivery_city_id { get; set; }
public string delivery_address { get; set; }
public virtual bs_cities bs_cities { get; set; }
}
and the second one:
public partial class bs_cities
{
public bs_cities()
{
this.bs_delivery_type = new HashSet<bs_delivery_type>();
}
public decimal cities_id { get; set; }
public string cities_name { get; set; }
public virtual ICollection<bs_delivery_type> bs_delivery_type { get; set; }
}
and I have such ViewBag's for dropdownlist's:
ViewBag.city = new SelectList(_db.bs_cities, "cities_id", "cities_id");
ViewBag.delivery_adress = new SelectList(_db.bs_cities, "delivery_id", "delivery_address");
When I choose city in first dropdownlist, in the second one there has to be appeared binded list with delivery_adress, where delivery_city_id = cities_id(from first dropdownlist).
How to do that?
Edit:
I tryed method from #Izzy's comment, so here is my actual view:
#model Bike_Store.Models.DeliveryModel
#{
ViewBag.Title = "Checkout";
}
<script src="~/Scripts/bootstrap.min.js"></script>
<script src="~/Scripts/jquery-3.1.1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
<script type="text/javascript">
function GetDelivery(_stateId) {
var procemessage = "<option value='0'> Please wait...</option>";
$("#ddldelivery").html(procemessage).show();
var url = "/Shop/GetDeliveryByCityId/";
$.ajax({
url: url,
data: { cities_id: _stateId },
cache: false,
type: "POST",
success: function (data) {
var markup = "<option value='0'>Select adress</option>";
for (var x = 0; x < data.length; x++) {
markup += "<option value=" + data[x].Value + ">" + data[x].Text + "</option>";
}
$("#ddldelivery").html(markup).show();
},
error: function (reponse) {
alert("error : " + reponse);
}
});
}
</script>
<h2>Checkout</h2>
#using (Html.BeginForm())
{
#Html.DropDownListFor(m=>m.CitiesModel, new SelectList(Model.CitiesModel, "cities_id", "cities_name"), new {#id = "ddldelivery", #style="width:200px", #onchange="javascript:GetDelivery(this.value);"})
<br />
<br />
<select id="ddldelivery" name="ddldelivery" style="width:200px">
</select>
<br /><br />
}
My controller now looks like this:
public List<bs_cities> GetAllCities()
{
List<bs_cities> cities = new List<bs_cities>();
foreach (var city in _db.bs_cities)
{
cities.Add(city);
}
return cities;
}
public List<bs_delivery_type> GetAllDeliveries()
{
List<bs_delivery_type> deliveries = new List<bs_delivery_type>();
foreach (var delivery in _db.bs_delivery_type)
{
deliveries.Add(delivery);
}
return deliveries;
}
[HttpPost]
public ActionResult GetDeliveryByCityId(decimal cities_id)
{
List<bs_delivery_type> delivery = new List<bs_delivery_type>();
delivery = GetAllDeliveries().Where(m => m.delivery_city_id == cities_id).ToList();
SelectList objDelivery = new SelectList(delivery, "delivery_id", "delivery_address", 0);
return Json(objDelivery);
}
public ViewResult Checkout()
{
DeliveryModel deliveryModel = new DeliveryModel();
deliveryModel.CitiesModel = new List<bs_cities>();
deliveryModel.CitiesModel = GetAllCities();
return View(deliveryModel);
}
The problem now is that i have 2 ddls, but works only first one.
In scrshot you can see I have a list of cities, when I choose a city, in this same ddl appears a list of delivery adresses, and when I choose adress - its desappears. What a magic? Help me please with Ajax.
List of cities
I guesse i fixed it, the problem was in:
#Html.DropDownListFor(m=>m.CitiesModel, new SelectList(Model.CitiesModel, "cities_id", "cities_name"), new {#id = "ddldelivery", #style="width:200px", #onchange="javascript:GetDelivery(this.value);"})
I changes #id = "ddldelivery" to #id = "ddlcity" and it works now
The following guide will show you:
Create a partial view
Takes cityid as input and outputs the delivery address list
Load partial view into your select
Note: Partial view solution may be overkill in this situation, but for similar problems it is actually quite usefull.
PartialView .cshtml
Filename: _deliveryTypePartial.cshtml
#model List<bs_delivery_type>
#foreach(var item in Model)
{
<option value="#item.delivery_id">
#item.delivery_address
</option>
}
Controller Code for Partial View:
public IActionResult _deliveryTypePartial(decimal city_id)
{
List<bs_delivery_type> model = context.bs_delivery_types.Where(row => row.delivery_city_id == delivery_city_id).ToList();
return PartialView(model);
}
And then Finally, for your AJAX
I notice that your two dropdownlists have identical ID's witch will cloud your javascript code and is considered bad practice, so for the purposes of this guide I will call the first dropdownlist:
ddlcity
Now, inside your onchange function for ddlcity:
$('#ddldelivery').load("/ControllerName/_deliveryTypePartial?city_id=" _stateId);
This should load the partial view into your second dropdown list.
PS: As I completed this question you had already used the direct ajax method, I agree that both methods are equally suitable in this case. You can perhaps use the method outlined here if the actual objects you need to populate are a lot more complex.
could you please help me with this:
I am creating a table of some items with their properties and values (over some time).
Looks like:
I want to change color of those values, lets say 0 will be green 1 blue 2 red.
DataView dv = new DataView(grid);
myGridView.DataSource = dv;
myGridView.DataBind();
If I need to be more specific, please tell me, I am not a PRO. I don't know where can I control the cell.
I'd also like to add mouse over the text (so it will show the date of occurrence of current value).
Maybe some function/javascript...?
Very simple and light weight solution using jQuery:
Code behind:
public partial class GridViewCellColourChange : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
gvItems.DataSource = this.GetData();
gvItems.DataBind();
}
}
private IEnumerable<Item> GetData()
{
var item1 = new Item { item = "itm1", prop1 = "23", prop2 = "asd", prop3 = "23d", values = "0-0-0-0-0" };
var item2 = new Item { item = "itm2", prop1 = "43", prop2 = "asd", prop3 = "23d", values = "0-0-0-0-0" };
var item3 = new Item { item = "itm3", prop1 = "53", prop2 = "asd", prop3 = "23d", values = "0-0-0-0-0" };
return new List<Item> { item1, item2, item3 };
}
}
public class Item
{
public string item { get; set; }
public string prop1 { get; set; }
public string prop2 { get; set; }
public string prop3 { get; set; }
public string values { get; set; }
}
.ASPX:
<head runat="server">
<title></title>
<script src="https://code.jquery.com/jquery-1.12.2.min.js"></script>
<script>
$(function () {
$("#gvItems > tbody > tr").each(function (i, row) {
var children = $(row).children();
for(var i=0; i < children.length;i++)
{
var child = children[i];
if(child.localName == "td")
{
var text = $(child).text();
if(text == "23")
{
$(child).css("background-color", "red");
}
else if(text == "43")
{
$(child).css("background-color", "green");
}
}
}
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="gvItems" runat="server"></asp:GridView>
</div>
</form>
</body>
Output:
You can use gridview control with OnRowDataBound property to bind specific properties to the each cell/Row.
Use OnRowDataBoundEvent of gridview,here is sample
protected void GridCompany_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
foreach (GridViewRow gridViewRow in GridCompany.Rows)
{
if (gridViewRow.RowType == DataControlRowType.DataRow)
{
if (gridViewRow.Cells[6].Text.ToUpper() == "TRUE")// find your cell value and check for condition
{
// put here your logic
}
else
{
// put here your Else logic
}
}
}
}
I want design page like this
up to now I have created like this . I want to know bind check-box front of each row and send those checked/non-checked values with IDs using json and jquery
this last code snippet of that page
<div style="width:50%; float:left;text-align:left"><button id="resetborchure" type="button" class="btn btn-warning submit">Reset Brochure</button> </div>
<div style="width:50%; float:left;text-align:right"><button id="createborchure" type="button" class="btn btn-danger submit">Create Brochure</button> </div>
<script type="text/javascript">
</script>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/jqueryui")
<script type="text/javascript">
var url = '#Url.Action("FetchProductProperties")';
var editUrl = '#Url.Action("Edit")';
var type = $('#Type');
var category = $('#Category');
var country = $('#Country');
var product = $('#Product');
var template = $('#template');
var table = $('#table');
$('#search').click(function () {
table.empty();
$.getJSON(url, { type: type.val(), category: category.val(), country: country.val(), product: product.val() }, function (data) {
$.each(data, function (index, item) {
var clone = template.clone();
var cells = clone.find('td');
cells.eq(0).text(item.ID);
cells.eq(1).text(item.Name);
table.append(clone.find('tr'));
});
});
});
$('#resetborchure').click(function () {
table.empty();
});
</script>
}
Also I want , once I checked and click create brochure button I want send those checked/non-checked values with IDs using json
I have try to put to populate a checkbox with each listed result '<td><input type="checkbox" /></td>' inside cells.eq(1).text(item.Name);
as cells.eq(1).text('<td><input type="checkbox" /></td>'+item.Name); but this is not working
Once I click "Select Information" button Its list down data from AB_Product_Property table , IF I want to populate check-box with each search result row Do I need maintain boolean field in that table also ?? I want to do this without maintain column for that boolean field in AB_Product_Property table
Create a view model(s) to represent what you want to display/edit.
public class OptionsVM
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
public class SearchVM
{
public int Asset { get; set; }
public SelectList AssetList { get; set; }
public int Category{ get; set; }
public SelectList CategoryList { get; set; }
.... // other properties and SelectLists for the dropdownlists
public List<OptionsVM> Options { get; set; }
}
and in the GET method, populate the Options with the ID and Name properties
Then in the view
#model SearchVM
....
<form>
#Html.DropDownListFor(m => m.Asset, Model.AssetList)
....
#for(int i = 0; i < Model.Options.Count; i++)
{
#Html.HiddenFor(m => m.Options[i].ID)
#Html.CheckBoxFor(m => m.Options[i].IsSelected)
#Html.LabelFor(m => m.Options[i].IsSelected, Model.Options[i].Name)
}
<button type="button" id="createbrochure">Create Brochure</button>
and in the script
$('#createbrochure').click(function () {
$.getJSON(url, $('form').serialize(), function (data) {
....
});
})
and in the controller method
public ActionResult CreateBrochure(SearchVM model)
{
// To get the ID's of all selected options
IEnumerable<int> selectedOptions = model.Options.Where(o => o.IsSelected).Select(o => o.ID);
....
}
You can create new column for check box instead of appending check box to name column.
Than you can set class to that check box and get the checked or unchecked check box value using jquery.
I have this view. It's ok besides that I want to add: onclick="javascript:SubmitClick(#Model.id, answer.Id);" to definition of RadioButtons in it.
#model WebApplication2.Models.Question
<div>
#Html.HiddenFor(x => x.Id)
<h3> #Model.QuestionText </h3>
#foreach (var answer in Model.Answers) {
<p>
#Html.RadioButtonFor(b => b.SelectedAnswer, answer.Id) #answer.AnswerText
</p>
}
</div>
Question and Answer are models which look like that.
public class Question {
public int Id { set; get; }
public string QuestionText { set; get; }
public virtual ICollection<Answer> Answers { set; get; }
public string SelectedAnswer { set; get; } //this field is SET after clicking the radio button, I don't need this field ant this behaviour
}
public class Answer {
public int Id { set; get; }
public string AnswerText { set; get; }
}
As far as I know b => b.SelectedAnswer this expression inside #Html.RadioButtonFor makes that after click the field SelectedAnswer in class Question will be set. I don't need that I only need that only one of those radio buttons inside foreach loop can be selected at the same time and clicking on them invokes onclick="javascript:SubmitClick(#Model.id, answer.Id);". Also it can be done in obsolete way, just to make it work.
Screen which will help undestand how the view looks:
The view:
#model WebApplication2.Models.Question
<div>
#Html.HiddenFor(x => x.Id)
<h3> #Model.QuestionText </h3>
<form action="">
#foreach (var answer in Model.Answers) {
<p>
<input type="radio" onclick="javascript:SubmitClick(#Model.Id, #answer.Id);">#answer.AnswerText<br>
</p>
}
</form>
</div>
The script function is in strongly typed view against Person:
function SubmitClick(qid, aid) {
var url = '#Url.Action("SubmitSurvey", "Person")';
$.post(url, { questionId: qid, answerId: aid, personId:#Model.Id }, function (data) {
alert('questionId: ' + qid + ' answerId ' + aid);
});
}
Method invoked by script
public void SubmitSurvey(int questionId, int answerId, int personId) {
System.Diagnostics.Debug.WriteLine("UPDATING DATABASE " + "Selected personId: " + personId);
}
I have a list of Items that I want the user to sort using a Jquery sortable.
the structure of the items is like this:
public class SortableItems
{
public int Code { get; set; }
public byte? Priority { get; set; }
public string Name { get; set; }
public int IsActive { get; set; }
}
in my view I render the sortable inside a form in the following way:
#using (Html.BeginForm("TestAction", "TestController", FormMethod.Post, new { id = "submitTest" }))
{
<ul id="sortable" style="padding:0px;">
#for (int i = 0; i < Model.List.Count(); i++)
{
<li class="ui-state-default">
#Html.HiddenFor(x => Model.List[i].Code, new { #class = "id" })
#Html.HiddenFor(x => Model.List[i].Priority, new { #class = "order" })
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
#Model.List[i].Name
</li>
}
</ul>
<input type="submit" class="btn btn-primary" value="Update" />
}
Now the user can sort the N items in the list to their hearts desire. But I have not found a way to update the pidden value for Priority (order of the items that the user has sorted)
How can I persist the order of the items to my controller?
this is how I managed to solve the problem:
on the client side I did the following:
var neworder = new Array();
$("#sortable").disableSelection();
$("#sortable").sortable({
stop: function (event, ui) {
neworder = new Array();
$('#sortable li').each(function () {
//get the id
var id = $(this).attr("data-id");
neworder.push(id);
});
}
});
$(function () {
$('#submitTest').submit(function () {
if (neworder.length < 1) {
return false;
}
$.ajax({
url: "GuardarPrioridad", type: "POST", dataType: "json",
data: { orden: neworder.toString() },
success: function (result) {
$('#ShowResultHere').text(result);
$("#submitTest").hide();// .tex.html(result);
}
});
return false;
});
});
each time the user moves an element I update an array that conatins the IDs of the elements in the order that the user put them in.
I then submit this array via ajax and it is recieved by the controller.
and my controller looks like this:
public JsonResult SavePriority(string orden)
{
string[] data= orden.Split(',');
for (int i = 0; i < droguerias.Length; i++)
{
//save to DB
}
return Json("Saved!");
}