Hey guys so atm when the user goes to the holiday page, they can do 1 of 2 things
1)use a drop down box to select 'person name' and click 'view' this will display all the current holidays for this person
2)click 'create new' which will bring the user to a create page which allows them to add a new holiday(from here they select person name from drop and and select what date from calender)
This all works, however if the user originally follows the first path of selecting a person name and clicking view(it will display their holidays) if they then take the path of 2 and click 'create' it will jump to the create page. however the drop down box will be back at 'select' i would like the existing person selected from the previous drop down to display in this drop down.
A cookie or url/parameter?
anyway Im stuck please help
I've tried a cookie.
[code]
[HttpGet]
public ViewResult Index(string sortOrder, int? currentPersonID)
{
var holidays = db.Holidays.Include("Person");
HolidayList model = new HolidayList();
if (currentPersonID.HasValue)
{
model.currentPersonID = currentPersonID.Value;
}
else
{
model.currentPersonID = 0;
}
model.PList4DD = db.People.ToList();
//hyperlink to sort dates in ascending order
ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "date" : "";
var dates = from d in db.Holidays
where d.PersonId == currentPersonID.Value
select d;
switch (sortOrder)
{
case "date":
dates = dates.OrderBy(p => p.HolidayDate);
break;
}
model.HList4DD = dates.ToList();
var cookie = new HttpCookie("cookie_name", "currentPersonID");
Response.AppendCookie(cookie);
return View(model);
}
public ActionResult Create()
{
var cookie = Request.Cookies["cookie_name"];
if (cookie != null)
{
string value = cookie.Value;
//int? value = cookie.Value;
}
ViewBag.cookie = cookie.Value;
ViewBag.Id = new SelectList(db.People, "Id", "Name");
return View();
}
//tried to use the currentPersonID in index as an int but it woudlnt allow me.
[/code]
My View
[code]
#model HolidayBookingApp.Models.startANDend
#{
ViewBag.Title = "Create";
}
<p>
<span>#ViewBag.cookie</span>
<h2>Create</h2>
<form action ="ListHolidays" id="listHolidays" method="post">
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Holiday</legend>
<div>
#Html.LabelFor(model => model.PersonId, "Person")
</div>
<div>
#Html.DropDownListFor(model => model.PersonId,
new SelectList(ViewBag.Id, "Value", "Text"),
"---Select---"
)
#Html.ValidationMessageFor(model => model.PersonId)
</div>
<div>
#Html.LabelFor(model => model.HolidayDate)
</div>
<div>
#Html.TextBoxFor(model => model.HolidayDate)
#Html.TextBoxFor(model => model.endDate)
<script>
// Date.format = 'dd/m/yyy';
$("#HolidayDate").addClass('date-pick');
$("#endDate").addClass('date-pick');
//$('.date-pick').datePicker//({dateFormat: 'dd-mm-yy'}).val();
// clickInput: true
$(function () {
//3 methods below dont allow user to select weekends
$('.date-pick').datePicker(
{
createButton: false,
renderCallback: function ($td, thisDate, month, year) {
if (thisDate.isWeekend()) {
$td.addClass('weekend');
$td.addClass('disabled');
}
}
}
)
.bind('click',
function () {
$(this).dpDisplay();
this.blur();
return false;
}
)
.bind('dateSelected',
function (e, selectedDate, $td) {
console.log('You selected ' + selectedDate);
}
);
// HolidayDate is start date
$('#HolidayDate').bind('dpClosed',
function (e, selectedDates) {
var d = selectedDates[0];
if (d) {
d = new Date(d);
$('#endDate').dpSetStartDate(d.addDays(0).asString());
}
}
);
//end date is end date
$('#endDate').bind('dpClosed',
function (e, selectedDates) {
var d = selectedDates[0];
if (d) {
d = new Date(d);
$('#HolidayDate').dpSetEndDate(d.addDays(0).asString());
}
}
);
});
</script>
#Html.ValidationMessageFor(model => model.HolidayDate)
</div>
<p>
<input type="submit" value="Create"/>
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#*
<p>Current Person Selected is:
#TempData["currentPersonID"]
</p>*#
[code]
Once I get this going how can i get my drop down to store the value?
Any help?
Thanks
try to use the helper SelectList and pass to view a Model with a list of item and the id of the selected item.
#Html.DropDownList("name", new SelectList(Model.SomeList, "ItemValueId", "ItemDescription", Model.ItemValueId), new { #class = "someclass" })
To me, a cookie is a way of storing information across many different page and also if the user returns back after some time.
I would prefer using query string as the information needs to be passes from one page to other page. You can use javascript or jquery on 'Create' button click event, look to see if dropdown has a value, put it in a query string and redirect.
And I would suggest reading below:
http://www.codeproject.com/Articles/43457/Session-Cookie-Query-String-Cache-Variables-Unifie
Related
I have a view where the side menu (where PagedList is populating data with no problems) that are also links to display another set of data on the same view. Once these links are clicked, I want to have the data on that field to be changed and have the side menu (PagedList) to stay on the same page. I can pass the id value to my controller and display the data, but the "page number" value is not being passed.
Any ideas on how to accomplish that.
Here's what my code looks like
[HttpPost]
public ActionResult Index(string id, int? page)
{
try
{
id = Request.Form["newsLinkButton"];
ViewBag.Id = id;
using (myEntities db = new myEntities())
{
var getNews = db.News.Where(x => x.Show == "Yes").OrderByDescending(x => x.Date).ToList();
return View(getNews.ToPagedList(page ?? 1, 5));
}
}
catch (Exception ex)
{
return View(ex);
}
}
<div class="sidebar blue-sidebar news-sidebar no-mobile">
<h2>Recent News</h2>
#using (Html.BeginForm("Index", "News", FormMethod.Post))
{
<form id="newsForm" name="newsForm">
<ul class="white-text">
#foreach (var item in Model.OrderByDescending(x => x.Date))
{
<li>
<button id="newsLinkButton" name="newsLinkButton" type="submit" value="#item.Id">#item.Title</button>
</li>
}
</ul>
</form>
<div class="center-block">
#Html.PagedListPager(Model, page => Url.Action("Index", new { page }),
new PagedListRenderOptions()
{
DisplayLinkToFirstPage = PagedListDisplayMode.Always,
DisplayLinkToPreviousPage = PagedListDisplayMode.Always,
DisplayLinkToLastPage = PagedListDisplayMode.Always,
DisplayLinkToNextPage = PagedListDisplayMode.Always,
MaximumPageNumbersToDisplay = 3, // number of pages in line
DisplayEllipsesWhenNotShowingAllPageNumbers = false
})
</div>
}
</div>
Once again, thanks for your help in advance. I appreciate.
I found out that the property PageNumber is what holds the value for the page number (yeah, I know huh?). Therefore, I created #{ Session["page"] = Model.PageNumber; } and passed on to the controller. Problem solved. I hope this can help someone else in the future.
I'm using BeginCollectionItem with MVC 5 for adding and removing rows whenever.
One issue I'm having is with the delete function, I followed an online tutorial
which specified using #divId:first which seems to indicate deleting the first row whenever. This is no good for me, and wouldn't make sense to an end user.
As I'm using BCI I want to delete these from the html DOM so they won't have database Ids.
How do I delete by the Id of the model, this apparently (I think I read somewhere) is automatically generated by BCI?
Delete Function in the main view
$('#deleterow').live('click', function () {
$(this).parents('#newRow:first').remove();
return false;
});
Partial View with rows I want to delete by Id
#model Mvc.Models.Project
#using (Html.BeginCollectionItem("something"))
{
<div id="newRow">
#Html.LabelFor(m => m.Name)
#Html.EditorFor(m => m.Name)
Delete
</div>
}
Update 2
When viewing the rendered html the data-action attribute renders as 0 for all objects so the JQuery can't and won't delete a row/object from the view.
Update
Instead of the check box I want to use the Delete link button, I assume this is possible? Not very familiar with jQuery but it is something I intend to look at, fairly new to MVC too but this is what I have so far:
Main View
<h3>Students</h3>
<div id="newStudent">
#foreach(var Student in Model.students)
{
Html.RenderPartial("_Student");
}
</div>
<input type="button" id="addStudent" name="addStudent" value="Add Student"/>
<input type="submit" value="Submit"/>
#section Scripts
{
<script type="text/javascript">
$('#addStudent').on('click', function () {
$.ajax({
async: false,
url: 'School/AddNewStudent'
}).success(function (partialView) {
$('#newStudent').append(partialView);
});
});
$('#newStudent').on('click', '.deleteStudent', function () {
var id = $(this).data('id');
if (id === 0) { // assumes Id is integer
$(this).closest('.studentRow').remove();
}
else { // existing item - controller to delete from Db
var url = '#Url.Action("action", "controller")';
$.post(url, { ID: id }, function (response) {
if (response) {
$(this).closest('.studentRow').remove();
}
}).fail(function (response) {
// display error message
});
}
});
</script>
}
Partial View
#using (Html.BeginCollectionItem("students"))
{
<div id="studentRow">
#Html.HiddenFor(m => m.Id)
#Html.LabelFor(m => m.Name)
#Html.EditorFor(m => m.Name)
Delete
</div>
}
Controller
public class SchoolController : Controller
{
// GET: School
public ActionResult Index()
{
var newSchool = new School();
return View(newSchool);
}
public ActionResult AddNewStudent()
{
var student = new Student();
return PartialView("_Student", student);
}
[HttpPost, ActionName("DeleteStudent")]
public ActionResult DeleteStudent(School school)
{
foreach(var student in school.students.Where(s => !s.isDeleted))
{
return View(school.students);
}
return View();
}
}
What I have done is created a IsDeleted Property in Model/ViewModel, Put it in the Row as a Hidden Field, And also have a delete button against each Row
using (Html.BeginCollectionItem("Contacts"))
{
<div class="row mt-10">
#Html.HiddenFor(m => m.Id)
#Html.HiddenFor(m => m.isDeleted, new { data_is_deleted = "false" })
.......Removed HTML
<div class="col-md-1">
<span class="glyphicon glyphicon-trash" data-action="removeItem" title="remove" style="cursor:pointer"></span>
</div>
Then add this jQuery a JavaScript file. (Note: Don't add this to the Row Partial View, I add it in the View that calls the Row Partial View)
You might have to edit this jQuery to match your HTML structure, The goal in this jQuery is to update the IsDeleted field to either true or false and then Disable the other Input fields
$(document).on('click', '*[data-action="removeItem"]', function(e){
e.stopPropagation();
var btn = $(this);
var row = btn.closest('.row');
var parent = btn.parent();
var checkBox = parent.siblings('*[data-is-deleted]');
var checkBoxVal = checkBox.val();
if(checkBoxVal == 'False' || checkBox.val() == 'false'){
checkBox.val('true');
row.find('input, textarea, select').attr('readonly', 'readonly');
} else {
checkBox.val('false');
row.find('input, textarea, select').attr("readonly", false);
}
checkBoxVal = checkBox.val();
});
This is what your view will look like:
When post Back to Controller:
foreach (var contact in contacts.Where(s => !s.isDeleted))
{
// New and Updated Items
}
foreach (var contact in myModel.Where(s => s.isDeleted && s.Id!= 0))
{
// Deleted Items
// You don't have to delete Items where Id == 0, Bcz they are not in the DB.
// Just some Item added to the View and then deleted without Save
}
Deleted Items will be disabled: Note: You can Hide them by editing the above jQuery
EDIT A:
Actual controller code is something like this:
[HttpPost]
public ActionResult SaveStudent(Student model){
// Save model items
// Then Save the List of Items like this:
foreach (var contact in model.myListItems.Where(s => !s.isDeleted))
{
// New and Updated Items
}
foreach (var contact in model.myListItems.Where(s => s.isDeleted && s.Id!= 0))
{
// Deleted Items
// You don't have to delete Items where Id == 0, Bcz they are not in the DB.
// Just some Item added to the View and then deleted without Save
}
}
Firstly .live() was depreciated in jquery-1.7 and removed in 1.9. Use .on() instead. Next your generating invalid html by generating duplicate id attributes for the 'delete' link, which also means you will only ever be able to delete the first item and you never be able to delete newly added items because you are not using event delegation. Note also the BeginCollectionItem does not _ automatically generate the models ID_. All it does is add a prefix to the property name which includes an indexer value based on a guid so that the items can be bound to a collection on post back.
The link in your partial partial needs a class name and should store the Id value so it can be easily accessed in the script.
#using (Html.BeginCollectionItem("students"))
{
<div id="studentRow">
#Html.HiddenFor(m => m.Id)
#Html.HiddenFor(m => m.isDeleted) // not sure what the point of the data- attribute is
#Html.LabelFor(m => m.Name)
#Html.EditorFor(m => m.Name)
Delete
</div>
}
Then your script needs to be (note the id="newStudent" for the enclosing <div> is confusing since you foreach loop is generating the html for existing items)
$('#newStudent').on('click', '.deleteStudent', function() { // use event delegation
var id = $(this).data('id');
if (id == 0) { // assumes property Id is typeof int
// Its a new item so just remove from the DOM
$(this).closest('.studentRow').remove();
} else {
// Its an existing item so call controller to delete it from the database
var url = '#Url.Action(""DeleteStudent", "School")';
$.post(url, { ID: id }, function(response) {
if(response) {
// The student was successfully deleted
$(this).closest('.studentRow').remove();
}
}).fail(function (response) {
// Oops, something went wrong - display error message?
});
}
});
And the controller
[HttpPost]
public JsonResult DeleteStudent(int ID)
{
// delete the student from the database based on the ID and signal success
return Json(true);
}
hi I have MVC Razor application as e catalog and I used drop down-list to bind data from DB but the DDl bind the same value from DB as if I have three categories " x , Y , Z" the DDL returned similar values " Z ,Z , Z ".As it have the last value "y" . also I tried to insert the selected value "ID" to DB when user selected the item from DDL but I couldn't and it returned false selected value.
public class CategoryController : Controller
{
private AndriodContext db = new AndriodContext();
List<SelectListItem> items = new List<SelectListItem>();
List<string> category = new List<string>();
SelectListItem s = new SelectListItem();
//
// GET: /Category/
public ActionResult Index()
{
var x = db.Categories.Where(y => y.Active == true).ToList();
return View(x);
}
public ActionResult Create()
{
var data = db.Categories.ToList().Distinct();
List<string> x = new List<string>();
foreach (var t in data)
{
s.Text = t.Name;
s.Value = t.Cat_ID.ToString();
items.Add(s);
}
ViewBag.Parent = items;
return View();
}
//
// POST: /Category/Create
[HttpPost]
public ActionResult Create(Category category, IEnumerable<HttpPostedFileBase> files)
{
var data = db.Categories.ToList().Distinct();
List<SelectListItem> items = new List<SelectListItem>();
foreach (var t in data)
{
SelectListItem s = new SelectListItem();
s.Text = t.Name;
s.Value = t.Cat_ID.ToString();
items.Add(s);
if (s.Selected)
{ category.Parent_ID = int.Parse(s.Value); }
}
db.Categories.Add(category);
db.SaveChanges();
return RedirectToAction("Index");
}
}
#using (Html.BeginForm("Create", "Category", FormMethod.Post, new { enctype = "multipart/form-data", #data_ajax = "false" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend></legend>
<div class="editor-field create-Bt3">
#Html.DropDownList("Parent", new SelectList(ViewBag.Parent, "Value", "Text"), "- Select Parent -")
</div>
<div>
<p class="create-Bt ">
<input type="submit" value="Create" />
</p>
</div>
<br />
<br />
<div>
#Html.ActionLink("Back to List", "Index")
</div>
</fieldset>
}
you need to import jquery 1.7.1.min.js(DOM) in viewpage :
get the jquery DOM from jquery website(http://blog.jquery.com/2011/11/21/jquery-1-7-1-released/).
then in button click (<input type="submit" value="Create" onclick="GetDropDownValue();"/>) :
wrote a javascript function :
<script type="text/javascript" language="javascript">
function GetDropDownValue()
{
$("#hdnParentId").val($("#Parent").val());
}
</script>
The best practice to use a model to bind the dropdownlist instead of ViewBag.
If you don't want to use model the you can do one trick.
you put a hidden field(<input type="hidden" name="hdnParent" id="hdnParentId" />) in view page and calculate selected value of dropdownlis by simple jquery using :
$("#Parent").val();.
make the dropdownlist :
#Html.DropDownList("Parent", new SelectList(ViewBag.Parent, "Value", "Text"), "- Select Parent -",new{ id="Parent" });
After that you get a string parameter in HTTPPOST in controller :
[HttpPost]
public ActionResult Create(string hdnParent) //hdnParent is the name of dropdownlist
{
//now you can get the seleced value from "hdnParent".
//do the stuffs
return View();
}
I am very new with MVC. I have the following Razor code:
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset style="margin:5px">
<legend>List a Bicycle for Sale</legend>
<div class="editor-label">
#Html.LabelFor(model => model.BicycleManfacturer)
</div>
<div class="editor-field">
#Html.DropDownList("ManufacturerList")
</div>
....
....
<div class="float-right">
<input type="submit" value="List Bike" />
</div>
</fieldset>
}
"ManufacturerList" is a List of SelectedListItem stored in the ViewBag (I didn't want to create models for all my dropdown lists). It's build via this method:
private void HydrateManufacturerList()
{
var manufacturerList = (from row in db.BicycleManufacturer.ToList()
select new SelectListItem
{
Text = row.Description,
Value = row.BicycleManufacturerId.ToString()
}).ToList();
manufacturerList.Add(new SelectListItem
{
Text = "-- Select Manufacturer --",
Value = "0",
Selected = true
});
ViewBag.ManufacturerList = manufacturerList.OrderBy(row => row.Text);
}
I have the following code that gets called when a Submit is done:
[HttpPost]
public ActionResult Create(BicycleSellerListing bicyclesellerlisting)
{
bicyclesellerlisting.ListingDate = System.DateTimeOffset.Now;
if (ModelState.IsValid)
{
db.BicycleSellerListing.Add(bicyclesellerlisting);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(bicyclesellerlisting);
}
What I can't figure how to get the selected manufacturer from the dropdown list when the user posts the view back to my controller and this method is executed.
Use
public ActionResult Create(BicycleSellerListing bicyclesellerlisting, FormCollection collection)
{
...
You can get all the inputs including the drop down selected items like collection["ManufacturerList"] or similar depending on your drop down list name.
I hava a view where I have a list of links, being each link a region where the companies has offices.
Everytime I select a region, I get a list of processes. For every process, I get a dropdowlist from where to choose a owner of the process and a list of checkboxs of tests to choose.
In my controller, I get string[] OwnerId as the values selected in the dropdowlists.
The thing is, I get all values from all dropdowlists, not just those that were selected. How can I get just the ones I selected??
This is my view
#using CTTModel
#using TestingTool.ViewModels
#model TestRunModel
#{
ViewBag.Title = "Create";
}
<h2>
Create</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Regions</legend>
#foreach (Region region in Model.Regions)
{
#Html.ActionLink(#region.Name, "Create", new { id = region.Id })<br />
}
<div class="editor-field">
#foreach (ProcessModel process in Model.Processes)
{
<h1>#process.Name</h1>
**List<User> users = ViewBag.Users;
<select id="OwnerId" name="OwnerId" >
#foreach (User user in users)
{
<option value="#user.Id">#user.Name</option>
}
</select>**
<table>
<tr>
#{
int cnt = 0;
foreach (TestModel testModel in process.Tests)
{
if (cnt++ % 3 == 0)
{
#: </tr> <tr>
}
#: <td>
<input type="checkbox"
name="selectedTests"
value="#testModel.Id/#testModel.ProcessId/#testModel.RegionId"
#(Html.Raw(testModel.Active ? "checked=\"checked\"" : "")) />
#testModel.Name #:: #testModel.Description
#:</td>
}
#: </tr>
}
</table>
}
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<fieldset>
<legend>Test Screen</legend>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
And this is my controller. The Create Post does nothing yet, I'm trying to get the right values first.
//
// GET: /TestPreparation/Create
public ActionResult Create(int id = 1)
{
TestRunModel testRunModel = new TestRunModel();
foreach (Region region in _db.Regions)
{
testRunModel.Regions.Add(region);
}
TestRun testRun = _db.TestRuns.OrderByDescending(x => x.Id).First();
foreach (TestRunProcessRegion region in testRun.GetProcessesForRegion(_db.Regions.Single(i => i.Id == id)))
{
ProcessModel process = new ProcessModel
{
Code = region.ProcessRegion.Process.Code,
Description = region.ProcessRegion.Process.Description,
Name = region.ProcessRegion.Process.Name,
Process = region.ProcessRegion.Process.Id
};
foreach (SubProcess subProcess in region.ProcessRegion.Process.SubProcesses)
{
foreach (Risk risk in subProcess.Risks)
{
foreach (Test test in risk.Tests)
{
TestModel testModel = new TestModel
{
Id = test.Id,
Name = test.Name,
Description = test.Description,
ProcessId = region.ProcessRegion.Process.Id,
RegionId = region.ProcessRegion.Id
};
process.Tests.Add(testModel);
}
}
}
testRunModel.Processes.Add(process);
}
var users = new List<User>();
foreach (User user in _db.Users)
{
users.Add(new User
{
Id = user.Id,
Name = user.Name,
});
}
ViewBag.Users = users;
return View(testRunModel);
}
//
// POST: /TestPreparation/Create
[HttpPost]
public ActionResult Create(string[] OwnerId, string[] selectedTests, string[] processes)
{
if (ModelState.IsValid)
{
//_db.TestRunStatus.Add(testrunstatus);
//_db.SaveChanges();
return RedirectToAction("Index");
}
return View();
}
The reason why you are not getting any data back is because the method signature of your Post Action needs to be
public ActionResult Create(string OwnerId ...) //preferably int depending on what OwnerId is
This is because you only select one item out of the drop down box. So if you use this signature as opposed to string[], the Model binder will pass the selected value back to your action.
Having said this, it is better practice and the "MVC Way" to use,
Html.DropDownFor(x => x.UserID) it really makes things easier :)
This applies to all html input controls:
http://www.asp.net/mvc/tutorials/getting-started-with-aspnet-mvc3/cs/examining-the-edit-methods-and-edit-view
UPDATE
I think the best thing to do would be to add an OwnerID to the ProccessModel class.
Becuase ProccessModel looks to be IEnumberable<ProccessModel> Processes contained in the ViewModel you can get the Model to Bind in the following way using the defult MVC model binder.
Phil Haack has bloged about binding to lists here:
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Adapting from Phil's post I think you will have to do something like this:
<% for (int i = 0; i < Model.Processes.Count; i++) { %>
<%: Html.SelectListFor(model => model.Processes[i].OwnerID, (IEnumerable<SelectListItem>)ViewBag.Users) %>
<% } %>
Change the ViewBag.User to:
var users = _db.Users.Select(x => new SelectListItem(){
text = x.Name,
value = x.Value
});
Modify the Post Action:
[HttpPost]
public ActionResult Create(TestRunModel model)
{
foreach(var process in model.Porcesses)
{
process.OwnerID // This should be a user selected value
}
// code removed for brevity
}
I could help with getting the TestModel values if you like but I need to do some work now ;)