Understanding how DropDownListFor is working in MVC3 - asp.net-mvc

I'm new to MVC3 and have been working on a small site using EF and 'Code First'. I'm trying to do a few things in a view dealing with a drop down list and am wondering what the best way to go about them is. I want a user to be able to select a rule from the dropdownlist, and depending upon which rule was selected, I would like a label on the page to show the rule name (without posting). I also need to be able to send the selected rule onto the next page. I haven't added all of the necessary fields to the view yet because I'm really at a loss on how it should work. How should I go about trying to do this?
I've got my model:
public class D1K2N3CARule
{
public int ID { get; set; }
[Required]
public int Name { get; set; }
[Required]
public string Rule { get; set; }
public D1K2N3CARule(int name, string rule)
{
Name = name;
Rule = rule;
}
public D1K2N3CARule()
{
Name = 0;
Rule = "";
}
}
My ViewModel:
public class D1K2N3CARuleViewModel
{
public string SelectedD1K2N3CARuleId { get; set; }
public IEnumerable<D1K2N3CARule> D1K2N3CARules { get; set; }
}
My Controller:
public ActionResult Index()
{
var model = new D1K2N3CARuleViewModel
{
D1K2N3CARules = db.D1K2N3DARules
};
return View(model);
}
and my View:
'#model CellularAutomata.Models.D1K2N3CARuleViewModel
#{
ViewBag.Title = "Index";
}
<asp:Content id="head" contentplaceholderid="head" runat="server">
<script type="text/javascript">
</script>
</asp:Content>
<h2>Index</h2>
<table>
<tr>
<td>
#Html.DropDownListFor(
x => x.D1K2N3CARules,
new SelectList(Model.D1K2N3CARules, "ID","Rule")
)
</td>
</tr>
</table>'

I want a user to be able to select a rule from the dropdownlist, and depending upon which rule was selected, I would like a label on the page to show the rule name (without posting)
You will need javascript here. jQuery would be perfect for the job. I would start by providing a deterministic id for the dropdown because if you run this view inside a template there could be prefixes added to the id which would ruin our javascript id selectors (see below):
#Html.DropDownListFor(
x => x.D1K2N3CARules,
new SelectList(Model.D1K2N3CARules, "ID", "Rule"),
new { id = "ruleDdl" }
)
then provide some container which will receive the selected value:
<div id="ruleValue" />
and finally in a separate javascript file subscribe for the change event of the dropdown list and update the container with the selected value/text:
$(function() {
// subscribe for the change event of the dropdown
$('#ruleDdl').change(function() {
// get the selected text from the dropdown
var selectedText = $(this).find('option:selected').text();
// if you wanted the selected value you could:
// var selectedValue = $(this).val();
// show the value inside the container
$('#ruleValue').html(selectedText);
});
});
I also need to be able to send the selected rule onto the next page.
You could put your dropdown inside a form
#using (Html.BeginForm("NextPage", "Foo"))
{
#Html.DropDownListFor(
x => x.D1K2N3CARules,
new SelectList(Model.D1K2N3CARules, "ID","Rule")
)
<input type="submit" value="Go to the next page" />
}
and the NextPage controller action will receive the selected value.

Related

asp.net mvc displaying dropdown value

I have created a dropdownlist by fetching data from database.I want to display the selected value on click of submit. In controller I am trying to store the selected value in ViewBag and display it. When I debugged the code, I came to know that viewbag stores null value.The following line stores the value in viewbag.
ViewBag.scode = emp.Service_Code;
While debugging, Service_Code shows the value but it gets stored as null in ViewBag. Please help me in solving this issue.
Model
public class Employee
{
public int Service_Code { get; set; }
public string Service_Name { get; set; }
public IEnumerable<SelectListItem> ser_code { get; set; }
}
View
#model mvclearn.Models.Employee
#{
ViewBag.Title = "menu";
}
<link href="~/Content/bootstrap.css" rel="stylesheet" />
<div class="container">
#using (Html.BeginForm("save", "Test", FormMethod.Post))
{
#Html.DropDownListFor(m => m.Service_Code, Model.ser_code, "--select-",new { #class = "form-control" })
<input type="submit" value="submit" class="btn-block" />
}
</div>
<div>You entered:#ViewBag.scode</div>
Controller
public ActionResult menu()
{
RevenueDashboardEntities rdb = new RevenueDashboardEntities();
var model = new Employee()
{
ser_code = new SelectList(db.Services, "Service_Code", "Service_Name")
};
return View(model);
}
[HttpPost]
public ActionResult save(Employee emp)
{
RevenueDashboardEntities rdb = new RevenueDashboardEntities();
ViewBag.scode = emp.Service_Code;
return View("menu");
}
The selected value is already getting post in the action via model in Service_Code property of it.
What you need here is return your model back to view and it will populate the selected value with what was selected at form post:
[HttpPost]
public ActionResult save(Employee emp)
{
RevenueDashboardEntities rdb = new RevenueDashboardEntities();
// this is needed to populate the items of dropdown list again
emp.ser_code = new SelectList(db.Services, "Service_Code", "Service_Name");
// sending model back to view
return View("menu",emp);
}
Now the value will be auto selected on page load after form is posted and you can display the value on the page inside div by writing:
<div>You entered: #Model.Service_Code</div>

Implementing pagin / sorting / filtering in View with POST Form

I have an application in MVC 4 / C# / Visual Studio 2010 SP1. It is to create UI for storing collections of books. The information I want to store are: a name of a collection, a date on creation, and the list of books. A number of books is to be added from the database that stores all the books. Actually, another view is to edit books themselves.
So far, I have designed my View such that it shows form fields for name of collection and date on creation. But underneath I included list of all books to be selected.
Selecting them in the edit / create view means they are added to collection. I thought I could implement paging / sorting / filtering for the list of books as the number may become too large to show it on one page. My idea is to add PartialView with a list of books. The PartialView can be invoked by jQuery by .post() that is trggered by events like clicking on a page number, table column etc. The PartialView would store a page no., a sort criterium, filter criteria in some hidden fields and based on their values it would generate portion of the list. Hidden fields would be updated from the model but would also pass paging / sorting back to action.
I run into problem of how to put everything together in POST form. I would like a user to click page numbers while the previously selected books would still be selected. I don't know how to refresh a PartialView and keep books' state. I hope it is possible. If not, what would you recommend?
Thanks
Below is my application.
The model of a book:
// Entity
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
public DateTime DatePublished { get; set; }
}
ViewModels:
// BookToSelect view model
public class BookToSelect : Book
{
public bool Isselected { get; set; }
public static IList<BookToSelect> MapBooksToBooksToSelect(IList<Book> list, bool isselected = false)
{
return list.Select(x => new BookToSelect() { //...})
}
public static IList<Book> MapBooksToSelectToBooks(IList<BookToSelect> list)
{
return list.Select(x => new Book() { //... })
}
}
// List of books view model
public class ListOfBooks
{
public IList<BookToSelect> Books { get; set; }
public DateTime DayOnCreationThe { get; set; }
public string CollectionName { get; set; }
public static IList<Book> GetListOfBooks()
{
return new List<Book>() {
// ... set of new Books() { },
};
}
}
Controller / Action:
public class TestCollectionController : Controller
{
[HttpGet, ActionName("Edit")]
public ActionResult Edit_GET()
{
ListOfBooks ViewModel = new ListOfBooks();
ViewModel.Books = ListOfBooks.GetListOfBooksToSelect();
ViewModel.DayOnCreation = DateTime.Today;
ViewModel.CollectionName = "List of random books";
return View(ViewModel);
}
[HttpPost, ActionName("Edit")]
public ActionResult Edit_POST(ListOfBooks ViewModel)
{
return View(ViewModel);
}
}
and View:
#using MvcDbContext.ViewModels
#model ListOfBooks
#{
ViewBag.Title = Model.CollectionName;
}
<h2>#Model.CollectionName</h2>
#using (Html.BeginForm())
{
#Html.EditorFor(m => m.CollectionName)
#Html.EditorFor(m => m.DayOnCreation)
<table>
<tr>
<th class="display-label">#Html.DisplayNameFor(m => m.Books.FirstOrDefault().Isselected)</th>
<th class="display-label">#Html.DisplayNameFor(m => m.Books.FirstOrDefault().Title)</th>
<th class="display-label">#Html.DisplayNameFor(m => m.Books.FirstOrDefault().Author)</th>
<th class="display-label">#Html.DisplayNameFor(m => m.Books.FirstOrDefault().DatePublished)</th>
</tr>
#for (int i = 0; i < Model.Books.Count(); i++)
{
<tr>
#Html.EditorFor(m => m.Books[i])
</tr>
}
<tr>
<td colspan="3"><input type="submit" name="SaveButton" value="Save" /></td>
</tr>
</table>
}
As you've already determined, if you switch out the HTML with the next page, all the inputs, included their state, are replaced as well. As a result, the only way to handle this is to offload the state into an input outside of the replacement.
The simplest way to handle this would most likely be creating a hidden input that will consist of a comma-delimited string of ids of selected items. Just add some JS that will watch the checkboxes or whatever and add or remove items from this hidden input. You can then just post this string back and use Split to turn it into a list of ids that you can use to query the appropriate books and add them to the collection on the entity.

save position from all draggable divs on save mvc

I want to make a table arrangement system for a restaurant admin page.
I want a table index page which shows all tables as divs inside a bigger div(map of the restaurant).
The restaurant van add tables and these tables be added to that index page.
The tables can be dragged with the jquery draggable function.
This page needs to have a save button and if clicked it needs to store all the tables positions to the database.
My model is like this:
public class table
{
public int id { get; set; }
public string tableName { get; set; }
public bool available { get; set; }
public float positionY { get; set; }
public float positionX { get; set; }
}
My Controller which does not have much now.
private BonTempsDbContext db = new BonTempsDbContext();
// GET: tafel
public ActionResult Index()
{
return View(db.Tafel.ToList());
}
// GET: Menu/Create
public ActionResult Create()
{
return View();
}
// POST: Menu/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "id,tafelNaam,beschikbaar,positionY,positionX")] Tafel tafel)
{
if (ModelState.IsValid)
{
db.Tafel.Add(tafel);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(tafel);
}
and my view looks like this:
#model IEnumerable<BonTempsMVC.Table>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<div class="VoegToeBtn">
<a href="/table/create">
<span class="btn btn-default">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Create new table
</span>
</a>
</div>
<div id="tablewrapper">
#foreach (var item in Model)
{
<div class="draggable ui-widget-content" id="#Html.DisplayFor(ModelItem => item.id)">
<p>#Html.DisplayFor(ModelItem => item.tablename)</p>
</div>
}
</div>
<script>
$(".draggable").draggable({
snap: ".draggable",
snapMode: "outer"
});
</script>
now there needs to be a button which executes a query that update all the table records with the right positions or only the tables which moved if that is possible.
You can create an input tag on your view page. You can specify the Action method which will be invoked when the button is clicked by specifying the onclick attribute. Also, you can pass parameters so that the method will receive the coordinates:
#using (Html.BeginForm("ActionMethodName","ControllerName",new {param1 = coordinate1, param2 = coordinate2}))
{
... your input, labels, textboxes and other html controls go here
<input class="button" id="Update" type="submit" value="Submit" />
}
Then inside your controller, you can write an Action method which will have 2 parameters; viz; param1 and param2 which will do the task of updating the table parameters by writing a linq query:
public ActionResult ActionMethodName(int param1,int param2)
{
//LINQ query goes here for updating table coordinates
}

In MVC view, when form is posted, request contains form values while all model fields are 0

Using Visual Studio 2010, MVC project
When my form is submitted (currently via javascript, but same results with a submit button), the action is getting an empty model with both of the fields in it being zero instead of containing the value I entered into the textbox. The Request object does contain the correct name/value pair in the Form collection.
Model values going the other way work fine - so based on my [HttpGet] CallDisplayHome() action, the form loads with the textbox value being 1.
If anyone has a clue as to why it would not work coming back via POST, I would sure appreciate it.
Model being used:
namespace TCSWeb.Models
{
public class CallDisplayModel
{
public int SelectedRowIndex;
public int SelectedLineID;
}
}
View:
#model TCSWeb.Models.CallDisplayModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<body>
/*
There a Jscript datatable here and a bunch of scripts for working with it in the header I am skipping because I am hoping they are not relevant
*/
<div>
#using (Html.BeginForm("Testing", "CallDisplay", FormMethod.Post, new { name = "submitSelLine" }))
{
#Html.TextBoxFor(m => m.SelectedLineID)
<p>
<input type="submit" value="Log On" />
</p>
}
</div>
<button onclick="SubmitSelCallRecord()">#LangRes.Strings.calldisplay_opencallrecord</button>
My controller actions:
[HttpGet]
public ActionResult CallDisplayHome()
{
TCSWeb.Models.CallDisplayModel temper = new CallDisplayModel();
temper.SelectedLineID = 1;
temper.SelectedRowIndex = 1;
return View(temper);
}
[HttpPost]
public ActionResult Testing(TCSWeb.Models.CallDisplayModel cdmodel)
{
return RedirectToAction("CallDisplayHome"); //breaking here, cmodel has zero for selectedlineid
}
You need to declare your CallDisplayModel variables as properties:
public int SelectedRowIndex { get; set; }
[Required]
public int SelectedLineID { get; set; }
You can also add a little bit of validation to make sure that the user provides the correct information.
Change your post method to the following:
[HttpPost]
public ActionResult Testing(TCSWeb.Models.CallDisplayModel temper)
{
//check if valid
if(ModelState.IsValid)
{
//success!
return RedirectToAction("CallDisplayHome");
}
//update error! redisplay form
return View("CallDisplayHome", temper);
}
And display the errors in your view like so:
#Html.ValidationMessageFor(m => m.SelectedLineID)
#Html.TextBoxFor(m => m.SelectedLineID)
I'm unsure what your submitSelCallRecord button is doing, as it is referencing the javascript that was omitted.

How to have one RadioButtons group display in EditorTemplates in ASP.Net MVC(3)

I have a list of items from which I want the user to be able to input some value select one
But the radio-buttons generated by the EditorTemplate are named like "Item[x].SelectedItemId" so they are totally independent from each other and I can't get the value...
Let's go show some code.
The model:
public class FormModel
{
public List<ItemModel> Items { get; set; }
public int SelectedItemId { get; set; }
}
public class ItemModel
{
public int ItemId { get; set; }
public string ItemName { get; set; }
public string SomeString { get; set; }
}
The view:
#model FormModel
#using (Html.BeginForm())
{
#Html.EditorFor(m => m.Items)
}
The editor template:
#model ItemModel
#Html.RadioButton("SelectedItemId", Model.ItemId)
#Model.ItemName <br/>
#Html.TextBoxFor(m => m.SomeString) <br/>
UPDATE
This is what I want:
This is what I get:
As a result, FormModel.SelectedItemId never gets the value of any radio-button.
What am I doing wrong?
It appears as though you are aware that setting the names for radio buttons to be the same is necessary to make them work. However, when you do that in an editor template by using the line of code #Html.RadioButton("SelectedItemId", Model.ItemId), MVC 3 will take into consideration that you are in an editor template for Items and prepend items[n].
This would create a name of something like name="Items[0].SelectedIndex". This would be fine if it weren't for the fact that the next radio button would be `name="Items[1].SelectedIndex".
One way to solve this is to not use an editor template and use a foreach loop instead. Here is some code that I was able to get functional. I confirmed that model-binding worked for the SelectedIndex.
#model FormModel
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm())
{
foreach (var item in Model.Items)
{
#Html.RadioButtonFor(x => x.SelectedItemId, item.ItemId)
#item.ItemName <br/>
#Html.TextBoxFor(m => item.ItemName) <br/>
}
<input type="submit" value = "submit" />
}
I had same problem, and we solved it with this piece of code.
#Html.RadioButton("", Model.Id, Model.Selected, new { Name = "deliveryMethod" })
You need to put Name property explicitly, so it will be used instead name that you get after EditorFor executes.

Resources