Need to select last ID from a viewdata - c#

I have an ViewData with my production orders in it. Im doing a thing where the operator can create a new production by selecting the production order he wants to work on, but the ideal was to show already the last production order created, instead of him having to go across all the options and select the last one. Can someone help me out?
I'm working with ASP-NET C# Razor Pages.
This is my ViewData
ViewData["production_order_ID"] = new SelectList(_context.Production_Order, "production_order_ID", "production_order_ID");
This is my page
<div class="col-md-2" style="margin-top:10px">
<label asp-for="Production.production_order_ID" class="control-label">Ordem de Produção:</label>
<select id="orderList" name="ids" asp-for="Production.production_order_ID" class="form-control" asp-items="ViewBag.production_order_ID" onchange="getSensors(); myFunction(event);"></select>
</div>
Now is showing the first item on the ViewData but i need to show the last one by default.

One way to do it is to use a viewmodel:
public class OrdersViewModel
{
public List<Order> Orders { get; set; }
public int Selected { get; set; }
}
Then in your action method create, popullate and pass the viewmodel into the view:
public IActionResult Index()
{
var orders = new List<Order>
{
new Order { OrderId = 1, OrderName = "Order # 1" },
new Order { OrderId = 2, OrderName = "Order # 2" }
};
var viewModel = new OrdersViewModel() {
Orders = orders,
Selected = orders.LastOrDefault().OrderId // get last order
};
return View(viewModel);
}
And the view:
#model MyWebApplication.Models.OrdersViewModel // use your namespace
<div class="col-md-2" style="margin-top:10px">
<label class="control-label">Ordem de Produção:</label>
<select id="orderList" name="ids" asp-for="#Model.Selected" class="form-control" asp-items="#(new SelectList(Model.Orders, "OrderId", "OrderName"))" onchange="getSensors(); myFunction(event);"></select>
</div>

So basically what i just did was
ViewData["production_order_ID"] = new SelectList(_context.Production_Order.Where(c => c.User.AspNetUser.UserName.Equals(User.Identity.Name)).OrderByDescending(c => c.production_order_ID).ToList(), "production_order_ID", "production_order_ID");
and worked just fine for what i intended to. Sorry for wasting your time guys, but thank you so much for your answer.

Related

.NET Core <select> With Default Value?

My goal is to generate a <select> dropdown with a certain select value (<option>) pre-selected, so the finalized HTML should look like this:
<select>
<option value = "1">Option1</option>
<option value = "2" selected>Option2</option>
<option value = "3">Option3</option>
</select>
Note that the option with a value of 2 has a selected attribute, indicating that it will show before the dropdown is clicked. I cannot (and am trying to) achieve this using .NET Core Tag Helpers.
This is my model (I think you can safely ignore the details):
public class ReportViewModel
{
[Display(Name = "Pick a form")]
public IEnumerable<Form> AvailableForms { get; set; }
public Form SelectedForm { get; set; }
public List<ReportData> FormResponses { get; set; }
}
Note that the Form object there just has Id and Name properties on it.
This is my select statement:
<label asp-for="SelectedForm.Name" class="form-control-label font-weight-bold"></label>
<select asp-for="SelectedForm.Name"
class="form-control"
onchange ="onFormSelected(this.value)"
asp-items="#(new SelectList(Model.AvailableForms, "Id", "Name"))">
</select>
I don't see the answer in the Microsoft Guide
Or in a blog on the topic
Basically you need to is set the select to use the SelectedForm.Id property, then specify the value of the form to be selected in your controller. I had to update your code a little but this works for me -
<label asp-for="SelectedForm" class="form-control-label font-weight-bold"></label>
<select asp-for="SelectedForm.Id"
class="form-control"
onchange ="onFormSelected(this.value)"
asp-items="#(new SelectList(Model.AvailableForms, "Id", "Name"))">
</select>
Then in your controller
var vm = new ReportViewModel()
{
AvailableForms = new List<Form>()
};
var form2 = new Form() { Id = 2, Name = "Bar" };
(vm.AvailableForms as List<Form>).Add(new Form() { Id = 1, Name = "Foo" });
(vm.AvailableForms as List<Form>).Add(form2);
(vm.AvailableForms as List<Form>).Add(new Form() { Id = 3, Name = "Baz" });
vm.SelectedForm = form2;
return View(vm);
The SelectList constructor can take an additional argument, namely selectedValue. In your case, you should be able to pass this through, which I think will look something like this:
asp-items="#(new SelectList(Model.AvailableForms, "Id", "Name", Model.SelectedForm.Id))"
I think the reason asp-for isn't working for you is the mismatch between the value of SelectedForm.Name (which is a string), and the value of the Id property you're using in the SelectList constructor (which is an integer?).
You can see partially how this works in the source code. You end up here in GenerateOption:
var selected = item.Selected;
if (currentValues != null)
{
var value = item.Value ?? item.Text;
selected = currentValues.Contains(value);
}
At this point, I believe currentValues will contain a single element, which will be a string (Form.Name). I believe also that item.Value will be e.g. "1" and so there's no match.
This is old, but I didn't see my approach here.
Pass it in with a viewbag from the controller.
<select>
<option>#ViewBag.selected</option>
<option>1</option>
<option>2</option>
<option>3</option>
</select>

Refactor the loop to merge one property when other properties are identical in ASP.net MVC Razor

I have a dataset that currently produces an output as follows:
Code:
Part 1: The View -
#foreach (var dt in Model.PlaceList) {
<tr class="Gap">
<td>
<div class="col-sm-12">
<h3>#dt.PlaceName</h3><br />
<span>#dt.OpenTimings</span><br />
<span>#dt.Slot</span><br />
<span>#dt.ActivityName</span><br />
<span>#dt.Address</span><br />
</div>
</td>
</tr>
}
Part 2: Data Retrieval from DB
var gPlaceList = (from l in _appdb.GetPlaceDetails
select new GetListPlaces {
PlaceName = l.PlaceName,
OpenTimings = l.OpenTimings,
Slot = l.Slot,
Activity = l.Activity,
Address = l.Address
}).ToList();
Part 3: Data structure used to populate the entries
public partial class GetListPlaces {
public string PlaceName { get; set; }
public string OpenTimings { get; set; }
public string Slot { get; set; }
public string Activity { get; set; }
public string Address { get; set; }
}
When looking at the result of output for one Place, we get groups of data that looke like so:
Current Output:
Place Name
Open Timings
Slot1
Activity
Address
Place Name
Open Timings
Slot2
Activity
Address
Place Name
Open Timings
Slot3
Activity
Address
Place Name
Open Timings
Slot4
Activity
Address
Place Name
Open Timings
Slot5
Activity
Address
We want to merge the result to look like this, for all results where the other 4 columns match.
Expected Output:
Place Name
Open Timings
Slot1, Slot2, Slot3, Slot4, Slot5
Activity
Address
The data here is just a sample. the real output in our website has thousands of results and merging the data like this will help us in reducing the display area as well as reduce duplication of data.
Group your data and show it comma separated using string extension method 'Join'
#foreach (var dt in Model.PlaceList.GroupBy(x=> new { x.PlaceName, x.OpenTimings, x.ActivityName, x.Address }))
{
<tr class="Gap">
<td>
<div class="col-sm-12">
<h3>#dt.Key.PlaceName</h3><br />
<span>#dt.Key.OpenTimings</span><br />
<span>#string.Join(",", dt.ToList().Select(x=>x.SlotNo))</span><br />
<span>#dt.Key.ActivityName</span><br />
<span>#dt.Key.Address</span><br />
</div>
</td>
</tr>
}
Use grouping! Just group records by the values that you expect to be same, and use Select to form a new record:
Model.PlaceList
.GroupBy(x => {x.PlaceName, x.OpenTimings, x.ActivityName, x.Address})
.Select(group => new
{
PlaceName = group.Key.PlaceName,
OpenTimings = group.Key.OpenTimings,
...,
Slots = String.Join(", ", group.Select(x => x.SlotNo))
})
Now one record will contain exactly the kind information you needed, and you can loop over the results of this query to output the view.

Getting the chosen item from DropDownList

I use JavaScript for populating a list called "groups".
Then I create a DropDownList:
<div class="form-group">
<div class="col-md-10">
#Html.DropDownList("groups", new SelectList(string.Empty, "Value", "Text"), "Choose...")
</div>
</div>
The DropDownList displays fine.
What I need to do is assign the chosen value from "groups" to the model.group_id.
I don't know how to get the item chosen in DropDownList in the controller method. Thank you for any advice.
If you need it to bind to group_id then use that as the name:
#Html.DropDownList("group_id", ...)
Or, even better, use the strongly-typed helper:
#Html.DropDownListFor(m => m.group_id, ...)
Assuming you have a form field in your form with the name group_id like this and you want to set the selected value from your dropdown to that field for some reason,
#Html.HiddenFor(s=>s.group_id)
<div class="form-group">
#Html.DropDownList("groups",new SelectList(string.Empty, "Value", "Text"), "Choose...")
</div>
You can listen to the change event of the dropdown and get the selected option value and set to the group_id
$(function(){
$("#groups").change(function(e){
var v=$(this).val();
$("#group_id").val(v);
});
});
I am not sure why you are loading the dropdown content via javascript, but there are other better ways to render a dropdown and pass the selected value back to your controller as explained in this post.
Add a SelectedGroup property to your view model
public class CreateSomethingViewModel
{
public int SelectedGroup {set;get;}
public List<SelectListItem> Groups {set;get;}
}
and in your GET action, If you want to load the Groups, you can do it
public ActionResult Create()
{
var vm = new CreateSomethingViewModel();
//Hard coded for demo. You may replace with your db entries (see below)
vm.Groups = new List<SelectListItem> {
new SelectListItem { Value="1","Chase bank" },
new SelectListItem { Value="2","PNCbank" },
new SelectListItem { Value="3","BOA" }
};
return View(vm);
}
And in your view
#model CreateSomethingViewModel
#using(Html.BeginForm())
{
#Html.DropDownListFor(s=>s.SelectedGroup,Model.Groups)
<input type="submi" />
}
With this you do not need to use any js code ( Even if you load the dropdown content via javascript), when user changes the dropdown option value, It will be set as the value of the SelectedGroup property.
[HttpPost]
public ActionResult Create(CreateSomethingViewModel model)
{
// check model.SelectedGroup
// to do : Save and return/redirect
}

C# MVC DropDownListFor List of Strings

I am working with a list of string items in mvc that needs to be selected from a drop down list. The drop down list is binding fine, and value's are setting fine, but even though the current item being iterated matches an item in the drop down list it isn't being pre-selected as it's value, can anyone point me in the right direction?
#for (var i = 0; i < Model.StringList.Count; i++)
{
if (BL.Helpers.StringHelpers.Validate(Model.DisplayStringSegments[i]))
{
<div id="editor-field">
#Html.DropDownListFor(m => m.StringList[i], Model.PosterOptions, String.Empty, new { })
</div>
}
else
{
<div id="editor-label">#Model.StringList[i]</div>
#Html.HiddenFor(model => model.StringList[i])
}
}
So for this case, the Options is a list of strings holding only one value, "Test" -> set both as Text and Value;
PosterOptions.Add(new SelectListItem() { Text = "Test", Value = "Test" });
Can anyone tell me why the current StringList[i] isn't being pre selected, even though it has the value of "Test" ?
For anyone that comes across this;
I had to "Hack" a solution, I did this by:
Changing my ViewModel's (Model.Options)
List<SelectListItem> to a List<string>
Changing my drop down list selection to the following, forcing the selected value;
<div id="editor-field">
#{
string currentString = Model.StringList.ElementAt(i).ToString();
}
#Html.DropDownListFor(m => m.StringList[i], new SelectList(Model.Options, currentString), String.Empty, new {})
</div>
Perhaps there is a better way, but this works!
Another way could be setting the current selected item during the list creation, like this:
PosterOptions.Add(new SelectListItem() { Text = "Test", Value = "Test", Selected = true });
I had the same issue and your response helped me. I don't think that's a "hack" though. Because in your question you were using the same SelectList for all the dropdownlists so even though you mention you didn't want to create multiple lists for the drop downs I can't see another way when you have multiple drop downs as you need to specify different selected values.
As a small refactoring you can get rid of the temp variable and access the selected value directly like this:
#Html.DropDownListFor(m => m.StringList[i], new SelectList(Model.Options, Model.StringList[i]), String.Empty, new {})
In your example you don't need to distinguish between text and value but in my case it was required. When that's necessary it can be accomplished by providing the value and text field names for the SelectList. For example, say you need multiple dropdowns with Country values such as:
Country class:
public class Country
{
public string Code { get; set; }
public string Name { get; set; }
}
Model:
public List<string> CustomerCountryList { get; set; }
public IEnumerable<Country> CountryList { get; set; }
and the View:
#Html.DropDownListFor(m => m.CustomerCountryList[i], new SelectList(Model.CountryList, "Code", "Name", Model.CustomerCountryList[i]))

Edit View with child entity selection listbox and HTTPPost difficulties

I have a Search Edit view which is strongly typed to my Search model class seen below (simplified).
I want to display the custodians that are attributed to the Search being edited in a listbox showing all Custodians, with the current ones selected.
My controller's Get Edit action is thus:
public ActionResult Edit(int id, int searchListId = 0)
{
if (searchListId != 0)
{
Session["CurrentSearchListID"] = searchListId;
}
ProjectContext mydb = db;
Search search = Search.Find(mydb, id);
IEnumerable<SelectListItem> selectedItems =
from c in Custodian.List(mydb)
select new SelectListItem
{
Selected = (search.Custodians.Contains(c)),
Text = c.CustodianName,
Value = c.ToString()
};
ViewBag.Custodians = selectedItems;
return View(search);
}
And my Views listbox is thus:
#{
//List<Kiersted.Keps.BusinessObjects.Custodian> Custodians = ViewBag.Custodians;
IEnumerable<SelectListItem> SelectedItems = ViewBag.Custodians;
}
#Html.ListBox("Custodians", SelectedItems);
This produces a listbox with the Custodians depicted, but none are selected (I have confirmed that several of the SelectListItems accurately describe the custodian as selected. I have tried using ListBoxFor and it produces the same thing when populated with a MultiSelectList.
Finally I decided to just force it to do what I want, but this does not return selected Custodians on Submit.
<select id="Custodians" multiple="multiple" name="Custodians">
#foreach (Kiersted.Keps.BusinessObjects.Custodian cust in Custodians)
{
if (Model.Custodians.Contains(cust))
{
<option value="#cust.CustodianID" selected="selected">#cust.CustodianName</option>
}
else
{
<option value="#cust.CustodianID" >#cust.CustodianName</option>
}
}
</select>
Anyone know how you are supposed to do this?
Edits:
ListBoxFor example
OK so after fiddling around with it for a while longer, I have now gotten Custodians selected in the listbox that correspond to the Search Custodians. Below is the view code:
<div class="editor-field">
#Html.ListBoxFor(model => model.Custodians, allCustodians.Select(cust => new SelectListItem {
Text = cust.CustodianName,
Value = cust.CustodianID.ToString(),
Selected = true}),
new { Multiple = "multiple" })
</div>
If I select several more custodians, how do I get them (or their corresponding values rather) back to the control upon submit?
Seeing that after your edit the problem boils down to multiple select model binding, perhaps you will find these useful?
How does a multiple select list work with model binding in ASP.NET MVC?
http://ittecture.wordpress.com/2009/04/30/tip-of-the-day-198-asp-net-mvc-listbox-controls/

Categories