Is it possible to use link inside DropDownList html helper? - c#

I have a model class named categories that retrieves data from database :
public class HomeController : Controller
{
private StoreContext db;
public HomeController()
{
db = new StoreContext();
}
public ActionResult Categories()
{
return View(db.Categories.ToList());
}
}
I want to use DropDownList helper method to display them in the view and I want all the categories inside it to be clickable, say, when you click them it has to adress you to the specified url belongs to the clicked category. Is there a way to make this happen with DropDownList helper? if yes then how?

You can do this but you have to use Jquery . If you ask how?
For example:
My sample entity
public class Category
{
public int Id { get; set; }
public string Url{ get; set; }
public string Name { get; set; }
}
My action:
public IActionResult Categories()
{
var list = new List<Category>();
for (int i = 0; i < 10; i++)
{
list.Add(new Category(){Id = i, Url = "https://stackoverflow.com", Name = "stackoverflow" });
}
var selectList = list.Select(x => new SelectListItem() {Value = Url, Text = x.Name})
.ToList();
return View(selectList);
}
in my View:
#Html.DropDownList("url",Model, "Choose a URL", new { id = "url_list" })
and then using jquery you could subscribe for the change event of this dropdownlist and navigate to the corresponding url:
$(function() {
$('#url_list').change(function() {
var url = $(this).val();
if (url != null && url != '') {
window.location.href = url;
}
});
});

Related

How to convert Actionlink group to Dropdown List

the SiteLanguage cs file:
public class SiteLanguages
{
public static List<Languages> AvailableLanguages = new List<Languages>
{
new Languages{ LangFullName = "English", LangCultureName = "en"},
new Languages{ LangFullName = "Español", LangCultureName = "es"},
new Languages{ LangFullName = "বাংলা", LangCultureName = "bn"}
};
public class Languages
{
public string LangFullName { get; set; }
public string LangCultureName { get; set; }
}
}
cshtml file:
#{
foreach (var i in MvcMultilingual.SiteLanguages.AvailableLanguages)
{
#Html.ActionLink(i.LangFullName, "ChangeLanguage", "Home", new{lang = i.LangCultureName}, null) <text> </text>
}
}
I want to convert this action list group to dropdown list. How to change this code? I mean I just want to change cshtml side. Html.ActionLink to Html.DropdownList etc.
Try the following:
#using Languages = MvcMultilingual.SiteLanguages
#Html.DropDownListFor(m => Languages.AvailableLanguages.GetEnumerator().Current,
Languages.AvailableLanguages.Select(d =>
{
return new SelectListItem() {
Text = d.LangFullName,
Value = Url.Action("SetLanguage", "Home", new { lang = d.LangCultureName })
};
}),
"-Select Language-",
new { id = "urlddl" })
See the javascript function for processing the change event in this post: is it possible do have Html.ActionLink inside a DropDownList Without java script?
Processing the selected value on the controller side:
public ActionResult SetLanguage(string lang)
{
...
}

Sending same form 2 or more times to controller in one ajax request

I have a problem which I have never encountered before, so here is a basic rundown.
I'm building a area on a website where users can submit warranty claims. Working on localhost so can't provide link.
I have one form where a user enters name etc.
I have another form where user enters product information, now this is where my problem lies. The user can add more than one item for their warranty claim.
So the next step is add another item, or submit warranty claim.
Now I don't want to add the data to the database until the user submits all their information, so clicks the submit warranty claim button.
At the moment I have a button to add another item, and when the user clicks the add another item button I send an ajax request to the server. Then I clear the product information form and then the user can add a second product.
So here is the code that is triggered when the user clicks the add another item button:
$.ajax({
cache: false,
url: '#(Url.RouteUrl("Nop.Plugin.Widgets.CustomerReturnsWidget.CustomerReturns.NoAccountWarrantyFormProduct"))',
type: 'post',
data: $("#add-warranty-claim-form-product-details").serialize(),
success: function (data) {
//reset form
$("#add-warranty-claim-form-product-details")[0].reset();
numItemsCount++;
}
});
Here is the ajax for final submit button:
$.ajax({
cache: false,
url: '#(Url.RouteUrl("Nop.Plugin.Widgets.CustomerReturnsWidget.CustomerReturns.NoAccountWarrantyFormYourDetails"))',
type: 'post',
data: $("#add-warranty-claim-form, #add-warranty-claim-form-product-details").serialize(),
success: function (data) {
console.log("success = " + data.success + ":");
}
});
As you can see I serialize both forms and send to controller. What would be the best way to go about this?
I thought maybe I could have a temporary table, where that product form gets entered into. Then if the user doesn't go through with the claim that data isn't entered into the warranty claim tables. Then I could build a task which would run once a week and delete everything from that temp product table which is older than one week. But I feel like there would be a better solution.
Now it's also worth noting I'm using validation on my models, so the model must be validated for the product form before another product can be added.
Here is my model:
namespace Nop.Plugin.Widgets.CustomerReturnsWidget.Models
{
[Validator(typeof(CustomerReturnsValidator))]
public partial class CustomerReturnsModel : BaseNopModel
{
public CustomerReturnsModel() {
Items = new List<CustomerReturnItemModel>();
}
public int CustomerReturnID { get; set; }
//customer details
[NopResourceDisplayName("Plugin.CustomerReturns.Fields.CustomerEmail")]
public string CustomerEmail { get; set; }
[NopResourceDisplayName("Plugin.CustomerReturns.Fields.CustomerFullName")]
public string CustomerFullName { get; set; }
[NopResourceDisplayName("Plugin.CustomerReturns.Fields.CustomerPhoneNumber")]
public string CustomerPhoneNumber { get; set; }
[NopResourceDisplayName("Plugin.CustomerReturns.Fields.InvoiceNumber")]
public int? InvoiceNumber { get; set; }
[NopResourceDisplayName("Plugin.CustomerReturns.Fields.DateSubmitted")]
public DateTime? DateSubmitted { get; set; }
public IList<CustomerReturnItemModel> Items { get; set; }
[Validator(typeof(CustomerReturnItemValidator))]
public partial class CustomerReturnItemModel : BaseNopModel
{
public CustomerReturnItemModel()
{
ClaimOptionTypeList = new List<SelectListItem>();
}
public int Id { get; set; }
public int CustomerReturnID { get; set; }
//claim form warranty
[NopResourceDisplayName("Plugin.CustomerReturns.Fields.ClaimOptionType")]
public string ClaimOptionType { get; set; }
[NopResourceDisplayName("Plugin.CustomerReturns.Fields.PurchaseDate")]
public string PurchaseDate { get; set; }
[NopResourceDisplayName("Plugin.CustomerReturns.Fields.ProductBrand")]
public string ProductBrand { get; set; }
[NopResourceDisplayName("Plugin.CustomerReturns.Fields.ProductBrandQuantity")]
public int ProductBrandQuantity { get; set; }
[NopResourceDisplayName("Plugin.CustomerReturns.Fields.ProductName")]
public string ProductName { get; set; }
public IList<SelectListItem> ClaimOptionTypeList { get; set; }
}
}
}
Here is the action result from my controller:
public ActionResult PartialNoAccountWarrantyProductFormView()
{
var model = new CustomerReturnsModel.CustomerReturnItemModel();
//type of claim form options
Dictionary<string, string> claimFormVals = new Dictionary<string, string>
{
{ "I'd like to submit a warranty claim", "0" },
{ "An item was damaged in transit", "1"},
{ "I'd like to return an item", "2" }
};
foreach (var val in claimFormVals)
{
model.ClaimOptionTypeList.Add(new SelectListItem
{
Text = val.Key,
Value = val.Value,
Selected = (model.ClaimOptionType != null && model.ClaimOptionType != "0") ? val.Value == model.ClaimOptionType : val.Value == "0"
});
}
return View("~/Plugins/Widgets.CustomerReturns/Views/CustomerReturns/PartialNoAccountWarrantyProductForm.cshtml", model);
}
For the add another item button I post to this controller method:
[HttpPost]
public ActionResult NoAccountWarrantyFormProduct(CustomerReturnsModel.CustomerReturnItemModel model, FormCollection form)
{
CustomerReturnsModel Model = new CustomerReturnsModel();
//IList<CustomerReturnItemModel> myList = new List<CustomerReturnItemModel>();
if (ModelState.IsValid)
{
//insert customer return items
model.ProductBrand = form["ProductBrand"];
model.ProductBrandQuantity = Int32.Parse(form["ProductBrandQuantity"]);
model.ProductName = form["ProductName"];
//myList.Add(model);
Model.Items.Add(model);
//return Json(new
//{
// success = true
//});
}
//If we got this far, something failed, redisplay form
return PartialNoAccountWarrantyProductFormView();
}
when final submit button occurs goes to this method.
[HttpPost]
public ActionResult NoAccountWarrantyFormYourDetails(CustomerReturnsModel model, FormCollection form)
{
CustomerReturns CustomerReturn = new CustomerReturns();//to customer return table
CustomerReturnItems CustomerReturnItem = new CustomerReturnItems();//to the items table
int CustomerReturnID;
if (ModelState.IsValid)
{
CustomerReturn.CustomerEmail = model.CustomerEmail;
CustomerReturn.CustomerFullName = model.CustomerFullName;
CustomerReturn.CustomerPhoneNumber = model.CustomerPhoneNumber;
CustomerReturn.InvoiceNumber = model.InvoiceNumber ?? CustomerReturn.InvoiceNumber;
CustomerReturn.DateSubmitted = DateTime.Now;
CustomerReturnID = _customerReturnsService.InsertCustomerReturn(CustomerReturn);
//insert customer return items
CustomerReturnItem.CustomerReturnID = CustomerReturnID;
CustomerReturnItem.ProductBrand = form["ProductBrand"];
CustomerReturnItem.ProductBrandQuantity = Int32.Parse(form["ProductBrandQuantity"]);
CustomerReturnItem.ProductName = form["ProductName"];
_customerReturnItemsService.InsertCustomerReturnItems(CustomerReturnItem);
var items = model.Items;
foreach (var CustomerReturnItems in items)
{
CustomerReturnItem.CustomerReturnID = CustomerReturnID;
CustomerReturnItem.ProductBrand = CustomerReturnItems.ProductBrand;
CustomerReturnItem.ProductBrandQuantity = CustomerReturnItems.ProductBrandQuantity;
CustomerReturnItem.ProductName = CustomerReturnItems.ProductName;
}
return Json(new
{
success = true,
CustomerReturnId = CustomerReturnID
});
}
//If we got this far, something failed, redisplay form
return View("~/Plugins/Widgets.CustomerReturns/Views/CustomerReturns/CustomerReturnsNoAccount.cshtml");
}
I'm not sure why this wouldn't work, seems so close.
I hope this makes sense.
Cheers

ASP.NET Actionlink with multiple variables is NULL

I am trying to send 2 variables to my controller with a Html.Actionlink, but everytime i do this, i get a NULL value, instead of the value i am trying to send.
This is my Html.Actionlink:
<ul>
#{ Spot selectedSpot = (Spot)Session["SelectedSpot"];}
#foreach (Spot spot in (List<Spot>)Session["AllSpots"])
{
if (selectedSpot != null)
{
if (selectedSpot.Id == spot.Id)
{
<li>#Html.ActionLink(spot.ToString(), "SetSpot", "EmsUser", new { selectedSpot = spot, user = Model }, new { #class = "selected"})</li>
}
else
{
<li>#Html.ActionLink(spot.ToString(), "SetSpot", "EmsUser", new { selectedSpot = spot, user = Model }, null)</li>
}
}
else
{
<li>#Html.ActionLink(spot.ToString(), "SetSpot", "EmsUser", new { selectedSpot = spot, user = Model }, null)</li>
}
}
</ul>
This is my controller:
public ActionResult SetSpot(Spot selectedSpot, User user)
{
Session["SelectedSpot"] = selectedSpot;
user.SetId(0);
return View("MakeReservation", user);
}
EDIT:
This is what the actionlink expects from me. "EmsUser" is the controller name and "SetSpot" is the action name
I figured out what the issue is. The route arguements specified in the ActionLink are posted as query string parameters to controller action. You can't add instance type in the route arguements. If you wish to pass the objects, you will have to do some work arounds. Please see below my suggestions:
Method 1:
Pass all the fields of the class individually in the route arguments. For e.g. lets say the classes are-
public class Model1
{
public int MyProperty { get; set; }
public string MyProperty1 { get; set; }
}
public class Model2
{
public int MyProperty2 { get; set; }
public string MyProperty3 { get; set; }
}
Your ActionLink should be:
#Html.ActionLink("Text", "SetSpot", "EmsUser",
new {
MyProperty = 1,
MyProperty1 = "Some Text",
MyProperty2 = 2,
MyProperty3 = "Some Text"
}, null)
Method 2:
Use ajax call as shown in this link

asp.net mvc Html.DropDownListFor: how to handle selected id

I have a problem with using #Html.DropDownListFor element.
What i have:
Model 'DatabaseModel':
public class DirectionEntity
{
public string Id { get; set; }
public string DirectionName { get; set; }
}
public class ViewModel
{
public int SelectedDirectionID { get; set; }
public List<DirectionEntity> DirectionList { get; set; }
}
Model 'DataFactory':
public class DataFactory
{
public static ViewModel Refresh()
{
using (var db = new MyDatabase())
{
return new ViewModel()
{
DirectionList = db.Directions.Select(_ => new { _.Id, _.DirectionName })
.ToList()
.Select(_ => new DirectionEntity() { Id = _.Id.ToString(), DirectionName = _.DirectionName })
.ToList(),
};
}
}
}
Controller:
public System.Web.Mvc.ActionResult AddNewDocument()
{
var db = DataFactory.Refresh();
return View(db);
}
[HttpPost]
public System.Web.Mvc.ActionResult AddNewEntry(ViewModel m)
{
m = DataFactory.Save(m);
ModelState.Clear();
return View(<some view>);
}
View:
#using (Html.BeginForm())
{
#Html.DropDownListFor(m => m.SelectedDirectionID, new SelectList(Model.DirectionList.Select(x => new SelectListItem { Value = x.Id.ToString(), Text = x.DirectionName }), "Value", "Text"), new { #class = "Duration", required = "required" })
<button type="submit" class="btn btn-default SaveAll">Save</button>
}
The question:
How to handle 'SelectedDirectionID' value, after user selected some position on dropdownlist, but not yet sent the request to the server using a POST-method.
See what the id of your dropdown is and then you can subscribe to the change event on the client side. You can do this using jQuery.
$("#idOfYourDropDown").change(function () {
// Do whatever you need to do here
// Here are some ways you can get certain things
var end = this.value;
var selectedText = $(this).find("option:selected").text();
var selectedValue = $(this).val();
alert("Selected Text: " + selectedText + " Value: " + selectedValue);
});
Also you should see my answer here on why you should not return a view from a POST action the way you are.
In this case you have to use Jquery. As per your view id for your drop down is 'SelectedDirectionID';
Your Js:
$(document).ready(function () {
var selectedValue = $('#SelectedDirectionID').val();
var selectedText = $("#SelectedDirectionID option:selected").text();
});
Or Inside drop down change event.
$('#SelectedDirectionID').change(function () {
var selectedValue = $(this).val();
var selectedText = $(this).find("option:selected").text();
});

Radiobutton acting like a checkbox MVC

With the code below, i can select multiple radio buttons at the same time, that is a problem, a true radio button only works with ONE selected item. How do i re-arrange my code so that it acts like a real radio button and not like a checkbox like the code below?
for (int i = 0; i < Model.RadioButtonItems.Count; i++)
{
<div>
#Html.HiddenFor(m => m.RadioButtonItems[i].RBName)
#Html.LabelFor(l => l.RadioButtonItems[i].RBIsSelected, Model.RadioButtonItems[i].RBName)
#Html.RadioButtonFor(r => r.RadioButtonItems[i].RBIsSelected, true);
</div>
}
The rest of code:
Model:
public class ModelVariables
{
public List<Item> RadioButtonItems { get; set; }
}
public class Item
{
public string RBName { get; set; }
public bool RBIsSelected { get; set; }
}
public static class Repository
{
public static List<Item> RBFetchItems()
{
return new List<Item>()
{
new Item() {RBName = "Metal"},
new Item() {RBName = "Jazz"},
new Item() {RBName = "Trance"}
};
}
}
Controller:
var selectedRBItems = model.RadioButtonItems.Where(x => x.RBIsSelected).Select(x => x.RBName).ToList();
if (model.RadioButtonItems != null && selectedRBItems.Count > 0)
{
ViewBag.RBResults = "Successfully Logged Pressed RB's!";
}
else
{
ViewBag.RBResults = "You must select a radio button!";
}
Summary: this code let's you select multiple radiobuttons, i DONT want that, i want only one possible selection out of many options.
Each radio button has a different name attribute so they are not grouped. Your model needs a property to bind the selected value to, and a collection of items for the options
public class ModelVariables
{
[Required(ErrorMessage = "...")]
public string SelectedValue { get; set; }
public List<string> Options { get; set; }
}
and in the GET method
var model = new ModelVariables()
{
Options = new List<string>() { "Metal", "Jazz", "Trance" },
SelectedValue = ? // set this if you want one of the buttons initially selected
};
return View(model);
and in the view
foreach (var option in Model.Options)
{
<label>
#Html.RadionButtonFor(m => m.SelectedValue, option, new { id = "" })
<span>#option</span>
</label>
}
// add the following if you do not set an initial value in the GET method
#Html.ValidationMessageFor(m => m.SelectedValue)

Categories

Resources