How to dynamically create checkboxes OR multi select on MVC 4 - javascript

In this project we have two list, one for the dealer and the second for his products.
So far if you check one dealer we get back all the product for this specific dealer, it implemented in javascript (Json).
Html (5 :)
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>DealerProduct</legend>
<div class="editor-label">
#Html.LabelFor(model => model.DealerID)
</div>
<div class="editor-field">
#Html.DropDownList("DealerID", String.Empty)
#Html.ValidationMessageFor(model => model.DealerID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ProductID)
</div>
<div class="editor-field">
#Html.DropDownList("ProductID", String.Empty)
#Html.ValidationMessageFor(model => model.ProductID)
</div>
<p>
<input type="submit" value="#Shared.Add" />
</p>
</fieldset>
}
JavaScript (Json :)
<script type="text/javascript">
$(document).ready(function()
{
$("#DealerID").change(function ()
{
var self = $(this);
var items="";
var url = "";
url = "#Url.Action("GetDealerProducts","DealerProduct")/"+self.val();
$.ajaxSetup({ cache: false });
$.getJSON(url,function(data)
{
$.each(data,function(index,item)
{
items+="<option value='"+item.Value+"'>"+item.Text+"</option>\n";
});
$("#ProductID").html(items);
$.ajaxSetup({ cache: true });
});
});
});
</script>
Controller :
public ActionResult GetDealerProducts(int id)
{
Dealer currentDealer = db.Dealers.Single(p => p.UserName == User.Identity.Name);
Dealer subDealer = db.Dealers.Single(s => s.DealerID == id);
List<Product> productOpenToSale = new List<Product>();
foreach (var item in currentDealer.ProductToSale)
if (!subDealer.ProductToSale.ToList().Exists(e => e.ProductID == item.ProductID))
productOpenToSale.Add(item.Product);
List<SelectListItem> productOpenToSaleList = new List<SelectListItem>();
productOpenToSale.ForEach(item => productOpenToSaleList.Add(new SelectListItem { Value = item.ProductID.ToString(), Text = item.ProductName }));
return Json(productOpenToSaleList, JsonRequestBehavior.AllowGet);
}
What I really need is adding (a pairing of) products dealer, which he can sell in the future.
Current option is to add products one by one, the desire is to give the possibility of multiple selection of all products.
Maybe something like dynamic checkBoxList or an foreach on a List from the ViewModel who add input - checkbox like this, but I don't know how to fill it after the dealer has selected on the first list and receive all the selected product back on submit..
10X for any help!! (&& sorry for my bad English :)

you can change this line of code
#Html.DropDownList("ProductID", String.Empty)
with something like this
<select id="SelectedItemIds" multiple="multiple" name="SelectedItemIds">
and having a viewModel on the server like this
class MyViewModel
{
public int[] SelectedItemIds { get; set; }
public int DealerID {get;set;}
}
and having a controller like this
[HttpPost]
public ActionResult Index(MyViewModel myViewModel)
{
return View();
}

I have similar situation and made it works here:
enter link description here
but I don't know how to pass the actual text back. I can only pass the index of selected items back to the controller. If you figure it out let me know.
Make sure your select name matches your variable name in the model.

Related

Struggling with filtering dropdown with another dropdown ASP.NET MVC

This is my first ASP.NET MVC application, and I'm really struggling with some stuffs, right now I have big issue and I'm stucked here for over 5 hours allready, I'm trying to filter my dropdown with selection from another dropdown, before I post my code I want to say that I've followed this post:
How to filter the options of a drop down list using another drop down list
So let's start:
Regardless of the others fields, I have a lets say two dropdowns also, one represent MAIN CATEGORY, another represent SUB CATEGORY, and on MAIN CATEGORY selection, SUB CATEGORY should be loaded in dropdown and user should be able to choose it.
I want to create view where user should be able to fill some date and post it back to server, but before he post it back he need to choose date properly MAINCATEG -> SUBCATEG so this is how I did it so far:
My action result 'Create' method:
public ActionResult Create()
{
// I did not wrote other stuffs because they are not important in my question and code will be clearer.
//First I'm filling MAIN CATEGORY dropdown with data from my database
List<Groups> articleGroups = GroupController.GetActiveMainGroups();
// Attach list on ViewBag, because this view Bag will be used to populate main dropdown
ViewBag.articleGroups = articleGroups;
//Here is second list which should populate second dropdown, right now I get all subgroups from database, because it didn't let me
//run my application if list was empty (probably I don't need this in future because I will filter second dropdown by selecting something from dropdown above)
List<SubGroups> subGroups = GroupController.GetAllSubGroups();
// Attach list on ViewBag, it will be used for generating dropdown list.
ViewBag.subGroups = subGroups;
return View(model);
}
Here is also one method which I thought I can call throught javascript by triggering event 'change' on first (main) dropdown:
public ActionResult GetSubgroupByMainGroup(Guid id)
{
List<SubGroups> subGroups = GroupController.GetAllSubGroupsByMainGroup(id);
return Json(subGroups, JsonRequestBehavior.AllowGet);
}
Here is my VIEW:
#model MyProject.Web.Models.ArticleNewViewModel
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
#using MyProject.Model
#{
ViewBag.Title = "Add new Article";
}
<h3>Adding new article to database</h3>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.MainGroupID, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.MainGroupID, new SelectList(ViewBag.articleGroups , "MainGroupID", "Group.Name"))
#Html.ValidationMessageFor(model => model.MainGroupID)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SubGroupID, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.SubGroupID, new SelectList(ViewBag.subGroups , "SubGroupID", "SubGroup.Name"))
#Html.ValidationMessageFor(model => model.SubGroupID)
</div>
</div>
//I don't understand this code really, because I have so little experience with javascript&jquery
<script type="text/javascript">
$(function () {
$("#MainGroupID").change(function () {
var val = $(this).val();
var subItems="";
$.getJSON("#Url.Action("GetSubgroupByMainGroup", "Article")", {id:val} ,function (data) {
$.each(data,function(index,item){
subItems+="<option value='"+item.Value+"'>"+item.Text+"</option>"
});
$("#SubGroupID").html(subItems)
});
});
});
</script>
}
<div>
#Html.ActionLink("Go back", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
It is interesting that when I set breakpoint in my method public ActionResult GetSubgroupByMainGroup(Guid id) it's not being hitted, that means this code is not executed, and here is my
ArticleNewViewModel
:
public class ArticleNewViewModel
{
[Required]
[Display(Name = "Article code")]
public string Code { get; set; }
[Required]
[Display(Name = "Article Title")]
public string Title { get; set; }
//Here is ID's which should represent value from MAIN and value from SUBGROUP
[Required]
[Display(Name = "Main group")]
public Guid MainGroupID { get; set; }
[Required]
[Display(Name = "Sub Group")]
public Guid SubGroupID { get; set; }
}
I probably did few mistakes here but I really don't know where and what, because I'm not familiar with javascript & jquery, and I don't know is there another way to do it :/
Whatever I would like to fix this so if someone of you guys might help me I would appreciate so much!
Thanks guys
Cheers

MVC 5 Razor view template binding hide script to a model radiobutton

Currently have a custom EditorTemplate which dynamically populates based on the incomming Model () in the Razor page.
The aim is to be able to hide the individual div 'Sub_Text' in the editor template based on the radio value.
Model: Prime.cs
public class Prime{
public List<QuestionModel> Questions { get; set; }
}
Model: QuestionModel.cs
public class QuestionModel{
public int Id { get; set; }
public string Question { get; set; }
public string Answer { get; set; }
public string SubText { get; set; }
}
Main View: _Reporting.cshtml
#model ViewModels.Prime
#for (int i = 0; i < Model.Questions.Count(); i++) //Dynamically generate and model bind database PolicyHolderKeyQuestions
{
#Html.EditorFor(x => x.Questions[i], "QuestionModel")
}
EditorTemplate: QuestionModel.cshtml
#model ViewModels.QuestionModel
#{
<div class="col-lg-2">
#Html.RadioButtonFor(Model => Model.Answer, YesNoNAOptions.Yes)
#Html.RadioButtonFor(Model => Model.Answer, YesNoNAOptions.No)
#Html.RadioButtonFor(Model => Model.Answer, YesNoNAOptions.NA)
</div>
<div class="col-lg-9">
<div class="row">
<p>
<strong>#Model.Question</strong>
</p>
</div>
<div class="row" name="**Sub_Text**"> #* **Hide Me!** *#
#Model.SubText
</div>
</div>
}
So far the closest idea I have found is to add a script something like this to the bottom of the template:
<script type="text/javascript">
$(':radio[name=Answer').change(function () {
// read the value of the selected radio
var value = $(this).val();
var doc
if (value == 1) {
$('#Sub_Text').show();
}else{
$('#Sub_Text').hide();
}
});
</script>
Which seems to be able to work for something simpler without using #Html.EditorFor() in a loop.
It looks as if the script does not follow the same automatic naming changes as those that happen to the RadioButtonFor elements. Resulting in things like this:
Radio:
<input id="Questions_0__Answer" name="Questions[0].Answer" type="radio" value="No" />
While the divs and scripts keep referencing only what was directly entered.
How can you dynamically hide the "Sub_Text" div based on the radiobutton when it is nested in this way?
If there is a way to do this without feeding in a script per EditorFor radio group that would be even better, but all solutions are welcome.
Wrap the html generated by the EditorTemplate in a container so that you can use relative selectors
#model ViewModels.QuestionModel
<div class="question"> // container
<div class="col-lg-2">
#Html.RadioButtonFor(Model => Model.Answer, YesNoNAOptions.Yes)
....
</div>
<div class="col-lg-9">
....
<div class="row">#Model.SubText</div>
</div>
</div>
and then the script can be
$(':radio').change(function () {
// get the associated element containing the SubText value
var row = $(this).closest('.question').find('.row');
if ($(this).val() == 1) {
row.show();
} else {
row.hide();
}
});
Side note: If your QuestionModel.cshtml is in the /Views/Shared/EditorTemplates or /Views/yourControllerName/EditorTemplates folder (which it should be) then the code in _Reporting.cshtml should be just
#model ViewModels.Prime
#Html.EditorFor(x => x.Questions)
No loop is required. The EditorFor() accepts IEnumerable<T> and generates the correct html for each item in the collection.

How to do update operation for show and hide div in mvc5?

Hi i want to do update operation for show and hide div in mvc5 . I will explain my issue with example.
This is my view. In this view i have one field called VisitType. If i clcik the Visit Type as DirectVisit the StartTime and EndTime field will be show(visible) othesewise it will be hide mode.
My Model (Visistors View Mode)
public bool VisitType { get; set; }
public string StartTime { get; set; }
public string EndTime { get; set; }
My View
<div class="col-sm-4" id="VisitType">
<div class="form-group">
<span style="color: #f00">*</span>
#Html.Label("Visit Type", new { #class = "control-label" })
<label>
#Html.RadioButtonFor(model => model.VisitType, "true", new { id = "" }) Telephone
</label>
<label>
#Html.RadioButtonFor(model => model.VisitType, "false", new { id = "" }) Direct Visit
</label>
</div>
</div>
<div id="StartTime">
<div class="col-sm-3">
<div class="foem-group">
#Html.Label("Start Time", new { #class = "control-label" })
#Html.TextBoxFor(model => model.StartTime, new { #class = "form-control ", type = "text" })
#Html.ValidationMessageFor(model => model.StartTime)
</div>
</div>
<div class="col-sm-3">
<div class="form-group">
#Html.Label("End Time", new { #class = "control-label" })
#Html.TextBoxFor(model => model.EndTime, new { #class = "form-control ", type = "text" })
#Html.ValidationMessageFor(model => model.EndTime)
</div>
</div>
</div>
My Jquery code
$(document).ready(function () {
$('#StartTime').hide();
$('#VisitType input[type="radio"]').change(function () {
if ($(this).val() === 'false') {
$('#StartTime').show();
}
else {
$('#StartTime').hide();
}
});
});
Now what i want is if i put one entry in my application by selecting the VisitType as Direct Visit and enter StartTime and EndTime ans Saved it. Now i want to change the VisitType as Telephone. So i click the Edit button and once it open the view it have to pass the value to Visit type radio button and also Start Time and end time time also need to be visible with values.
I passed the value to radio buttons in edit mode. But i donno hoe to visible the StartTime and EndTime in edit mode. I donno the exact j-query code. This is the issue. Please any one help me to resolve this issue.
The Code which i tried
Contrroller Code
public ActionResult Edit(Guid ?id)
{
WafeERP_NEWEntities db = new WafeERP_NEWEntities();
VisitorsViewModel objvisitorsviewmodel = new VisitorsViewModel();
View_VisitorsForm objviewvisitorsForm = db.View_VisitorsForm.Find(id);
if (objviewvisitorsForm.VisitType== true)
{
objvisitorsviewmodel.VisitType= true;
}
else
{
objvisitorsviewmodel.VisitType= false;
}
ViewBag.EmployeeID = new SelectList(db.Employees, "EmployeeID", "DisplayName", objviewvisitorsForm.EmployeeID);
ViewBag.CustomerID = new SelectList(db.Customers, "CustomerID", "DisplayName", objviewvisitorsForm.CustomerID);
objvisitorsviewmodel.VisitingID = objviewvisitorsForm.VisitingID;
objvisitorsviewmodel.Date = objviewvisitorsForm.VisitingDate;
objvisitorsviewmodel.VisitType= objvisitorsviewmodel.VisitType;
return View(objvisitorsviewmodel);
}
This code pass fetch the value from db and pass it to radio button correctly but now i want to show the starttime and endtime field with values once the view got open by clicking edit button. I tried my level best to explain the issue please any one help me to resolve this issue.
Advance thanks..
You should start by first wrapping the elements in a <div> so that you can show and hide them all rather than having to select all the associated labels, textboxes and validation message placeholders
<div id="date-controls">
#Html.LabelFor(m => m.StartTime)
#Html.TextBoxFor(m => m.STartTime)
....
</div>
and use css to initially hide them
#date-controls {
display:none;
}
then to display them initially if the value of VisitType is true, add the following script
var isVisit = '#Model.ContactMethod';
var dateControls = $('#date-controls');
if (isVisit == 'True') {
dateControls.show();
}
and also modify the script handling the radio buttons to
$('#VisitType input[type="radio"]').change(function () {
var selected = $('#VisitType input[type="radio"]:checked').val();
if (selected == 'true') {
dateControls.show();
} else {
dateControls.hide();
}
});
Side note: Your VisitType property should not be a bool. A bool should only be used for a property to which the answer can only be Yes or No, and the answer to What is the method of contacting us is not Yes or No, its by Telephone, or by Attending a meeting etc. By using a bool it also means that you have no flexibility to add other types in the future (your client might want to offer home visits to incapacitated people, or the option of video conferencing). Instead your property should be a collection or an enum.

Prevent from ajax call in MVC

Hi i am making my project in the asp.net,
basic expected behaviour -- fill form name , select master module(dropdown), select sub modules(dropdown), ajax passes id of submodule dropdown, create(submit).. it will submit all values,
now code is behaves---- fill form name, select master and submodule, while selecting submodule from second dropdown is calling the ajax call, and create action is called, so the form name and masterID(that is extracted from first dropdown) gone blank... so i need to prevent the ajax call to call the controller
Myform in razor view
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Form</legend>
<div class="editor-label">
#Html.LabelFor(model => model.FormName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FormName)
#Html.ValidationMessageFor(model => model.FormName)
</div>
<select id="State" name="state"></select><br />
<p>
<input id="sbmt" type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
My ajax call
$('#State').change(function () {
var a = $('#State').val();
var token = $('[name=__RequestVerificationToken]').val();
$.ajax({
url: "/form/create",
type: "POST",
data: { __RequestVerificationToken: token, 'SubID': a }
});
});
My controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Form form, int SubID)
{
if (ModelState.IsValid)
{
form.CreatedBy = 1;
form.SubId = SubID;
form.CreatedDate = DateTime.Now;
form.ModifyBy = 1;
form.ModifyDate = DateTime.Now;
form.IsActive = true;
form.IsDeleted = false;
db.Forms.Add(form);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.MasterID = new SelectList(db.Departments, "MasterId", "ModuleName", form.MasterID);
return View(form);
}
From the comments, you want to be able to post back the value of the selected state when you submit the form. The best approach would be to use a view model that includes the property SubId and bind your dropdownlist to that property (the SubId parameter in you POST method is then not necessary.
#Html.DropDownListFor(m => m.SubId, ....)
The alternative is to rename the control to SubId so it matches the parameter in your POST method
<select name="SubId" ...>
and delete the unnecessary javascript function $('#State').change(function () {...
I guess the easiest way for you would be to use MVC's ajax helpers. Change your form like so:
#using (Ajax.BeginForm("Create", "Home", null, new AjaxOptions { OnSuccess = "OnSuccess" }))
{
...
And afterwards add a javascript handler for onsuccess
function OnSuccess(){
alert("success");
}
This is barely functional code just to get you started.
PS. Make sure you add a reference to ~/Scripts/jquery.unobtrusive-ajax.min.js

Filter my #html.dropdownlistfor

Im working with a project and i need to filter my second dropdownlistfor based on my first dropdownlistfor value. Its simple to understand but hard to code it since i dont know jquery or javascript and im working in mvc asp.net, aswell as using a database in sql server where the data is located.
I need to filter my dropdown for project based on my dropdown for customer.
here is some of the code:
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>TimeEntry</legend>
<div class="editor-label">
#Html.Label("Customer")
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.TimeEntry.CustomerId, #customerSelectList)
#Html.ValidationMessageFor(model => model.TimeEntry.CustomerId)
</div>
<div class="editor-label">
#Html.Label("Project")
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.TimeEntry.ProjectId, #projectSelectList, "[ - No project - ]")
#Html.ValidationMessageFor(model => model.TimeEntry.ProjectId)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
public IEnumerable<Customer> Customers { get; set; }
public IEnumerable<Project> Projects { get; set; }
here is a code which i think is the code that is calling from the database but not really sure:
var customers = service.GetAllCustomers().ToList();
model.Customers = new SelectList(customers, "CustomerId", "Name");
var projects = service.GetAllProjects().ToList();
model.Projects = new SelectList(projects, "ProjectId", "Name");
Okay so you have a controller with a method that gives you the filtered projects like so:
public class FilterController:Controller {
public ActionResult Projects(int customerId) {
// I expect this call to be filtered
// so I'll leave this to you on how you want this filtered
var projects = service.GetAllProjects().ToList();
// at this point, projects should already be filtered with "customerId"
return Json(new SelectList(projects, "ProjectId", "Name"),
JsonRequestBehavior.AllowGet);
}
}
Then you call that method on the client like this:
// when the customer dropdown changes, you want to use the selected value
// and filter the projects dropdown - more like refresh it
$("#TimeEntry_CustomerId").change(function(){
refreshProjects($(this).val());
});
function refreshProjects(id) {
var projects = $("#TimeEntry_ProjectId");
$.get('#Url.Action("projects","filter")', {customerId:id},
function (result) {
// clear the dropdown
projects.empty();
// rebuild the dropdown
$.each(result, function (i, e) {
projects.append($('<option/>').text(e.Text).val(e.Value));
});
});
}

Categories

Resources