i have selectList with multiple attr which is filled through cascading(on select a company i just show selected Company Models) Now i want to allow user to select multiple models such that on select, item should add in c# list and display in page and then allow user to select more of any other company.Picture attached
Following is my code.
OrderViewModel
public class OrderViewModel
{
[Display(Name ="Order ID")]
public int order_id { get; set; }
[Required]
public string cus_name { get; set; }
public string cus_phone { get; set; }
public System.DateTime Date { get; set; }
[DataType(DataType.Date)]
public System.DateTime Date { get; set; }
public int Amount { get; set; }
public List<Products> Products { get; set; }
}
i want to bind selected Item in 'Products' List of OrderViewModel which will be send to server with Further fields.
Products
public class Products
{
public int id { get; set; }
public int modelId { get; set; }
public int Phoneid { get; set; }
public int Quantity { get; set; }
public double price { get; set; }
public bool isSelected { get; set; }
public int order_id { get; set; }
}
Razor View
<div class="form-group row">
<label class="control-label col-6">Company Name</label>
<div class="col-12">
<select id="CompanyId" class="custom-select mr-sm-2"
asp-items="#(new SelectList( #ViewBag.Companies,"Phoneid","Com_name"))">
<option value="">Please Select</option>
</select>
</div>
<span class="text-danger"></span>
</div>
<div class="form-group row">
<label class="control-label col-6"></label>
<div class="col-12">
<select id="modelId" multiple class="custom-select mr-sm-2"
asp-items="#(new SelectList(string.Empty,"modelId","model_name","--Select--"))">
<option value="">Please Select</option>
</select>
</div>
<span class="text-danger"></span>
</div>
what i have tried yet to add item in list
<script>
$("#modelId").change(function () {
var list = #(Model.Products);
let item = $(this).children("option:selected").val();
list.forEach(x => {
if (x.modelId != item) {
#{
Products products = new Products()
{
isSelected=true,
modelId= item,
};
Model.Products.Add(products);
}
}
});
})
#for (int i = 0; i < Model.Products.Count; i++)
{
}
</script>
I display all selected product throught partial view now i just want to send these selected products along with Quanity and Price of each to Server
Here is a working demo like below:
Model:
public class Model
{
[Key]
public int modelId { get; set; }
[Display(Name = "Model Name")]
public string model_name { get; set; }
public int Phoneid { get; set; }
public IList<Products> Products { get; set; }
}
public class Company
{
[Key]
public int Phoneid { get; set; }
[Display(Name = "Company Name")]
public string Com_name { get; set; }
}
public class Products
{
public int id { get; set; }
public int modelId { get; set; }
public int Phoneid { get; set; }
public int Quantity { get; set; }
public double price { get; set; }
public bool isSelected { get; set; }
public int order_id { get; set; }
}
View(Index.cshtml):
#model Products
<div>
<div style="float:left;width:40%">
<form id="form">
<div class="form-group row">
<label>Company Name</label>
<div class="col-12">
<select id="CompanyId" asp-for="Phoneid" class="custom-select mr-sm-2"
asp-items="#(new SelectList( #ViewBag.Companies,"Phoneid","Com_name"))">
<option value="">Please Select</option>
</select>
</div>
</div>
<div class="form-group row">
<label>Model Name</label>
<div class="col-12">
<select id="modelId" multiple class="custom-select mr-sm-2" name="modelId"
asp-items="#(new SelectList(string.Empty,"modelId","model_name","--Select--"))">
<option value="">Please Select</option>
</select>
</div>
</div>
<div>
<input type="button" id="saveBtn" value="Save" />
</div>
</form>
</div>
<div style="float:right;width:60%">
<h5>Products</h5>
<div id="products"></div>
</div>
</div>
#section Scripts
{
<script>
$(function () {
$('#CompanyId').change(function () {
var data = $("#CompanyId").val();
console.log(data);
$.ajax({
url: '/Home/GetModel?Phoneid=' + $("#CompanyId").val(),
type: 'Get',
success: function (data) {
var items = "<option value='0'>Select</option>";
$.each(data, function (i, item) {
items += "<option value='" + item.value + "'>" + item.text + "</option>";
});
$('#modelId').html(items);
}
})
});
$('#saveBtn').click(function () {
$.ajax({
url: '/Home/GetProduct?Phoneid=' + $("#CompanyId").val() + "&modelId=" + $('#modelId').val(),
type: 'Post',
success: function (data) {
$('#products').html(data);
}
})
})
})
</script>
}
Partial View(_Partial.cshtml):
#model IEnumerable<Products>
<table class="table">
<tbody>
#foreach (var item in Model)
{
<tr>
<td>check</td>
<td>
<input asp-for="#item.isSelected" />
</td>
<td>Product Id</td>
<td>
#Html.DisplayFor(modelItem => item.id)
</td>
</tr>
<tr>
<td>Quantity</td>
<td>
#Html.DisplayFor(modelItem => item.Quantity)
</td>
<td>Price</td>
<td>
#Html.DisplayFor(modelItem => item.price)
</td>
</tr>
}
</tbody>
</table>
Controller:
public class HomeController : Controller
{
private readonly MvcProj3Context _context;
public HomeController(MvcProj3Context context)
{
_context = context;
}
public IActionResult Index()
{
ViewBag.Companies = _context.Company.ToList();
return View();
}
public JsonResult GetModel(int Phoneid)
{
List<Model> model = new List<Model>();
model = (from m in _context.Model
where m.Phoneid == Phoneid
select m).ToList();
return Json(new SelectList(model, "modelId", "model_name"));
}
[HttpPost]
public IActionResult GetProduct(int Phoneid, string[] modelId)
{
var data = new List<Products>();
var ids = modelId[0].Split(',');
foreach(var item in ids)
{
var id = int.Parse(item);
//guess the modelA in CompanyA contains several products
var product = (from p in _context.Products
where p.Phoneid == Phoneid && p.modelId == id
select p).ToList();
foreach (var pro in product)
{
data.Add(pro);
}
}
return PartialView("_Partial", data);
}
}
Result:
Related
Hi everyone so Im in the process of developing a checkout system. Right now it works fine checking out one item at a time but I would like to be able to checkout multiple at a time using select2 jquery. I have it setup but for some reason my List Items property is returning null instead of storing the items that Im trying to check out and I cant seem to find the fix. Hoping someone can help me out here.
Here is theModel Class and View Model that I have tried:
public class CheckOutItem
{
private string _timeAsString = "";
public int Id { get; set; }
public string Department { get; set; }
public string Role { get; set; }
public string UserId { get; set; }
[NotMapped]
public List<string> Items { get; set; }
[DataType(DataType.DateTime)]
[DisplayFormat(DataFormatString = "{MM/dd/yyyy h:mm tt}")]
[Display(Name = "Date Checked Out")]
public DateTimeOffset DateCheckedOut { get; set; }
= DateTime.Now;
}
public class CheckOutItemVM
{
public int Id { get; set; }
[ForeignKey("Item")]
public int ItemId{ get; set; }
public Item Item{ get; set; }
[ForeignKey("Employee")]
public int EmployeeId { get; set; }
public Employee Employee { get; set; }
public string Department { get; set; }
public string Role{ get; set; }
public string UserId { get; set; }
[NotMapped]
public List<string> Items{ get; set; }
[DataType(DataType.DateTime)]
[Display(Name = "Date Checked Out")]
[DisplayFormat(DataFormatString = "{MM/dd/yyyy h:mm tt}")]
public DateTimeOffset DateCheckedOut { get; set; }
= DateTime.Now;
public Item GetItemInstance()
{
return new Item
{
Id = 0,
UserId = this.UserId,
Department = this.Department,
Role = this.Role,
DateCheckedOut = this.DateCheckedOut,
RecordedTime = this.RecordedTime,
Items = this.Items
};
}
}
Controller: "ItemID" in the ViewBag in CheckOutItem() is the string id of an item from the item class in the item database table
[HttpGet]
public IActionResult CheckOutItems()
{
ViewBag.ItemId = new SelectList(_db.Items.ToList(), "ItemID", "ItemID");
return View();
}
[HttpPost, ValidateAntiForgeryToken]
public IActionResult CheckOutItems(CheckOutItemVM iVM)
{
var checkout = iVM.GetItemInstance();
_itemManage.CheckOutItems(checkout);
return View(iVM);
}
View:
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$(".itemSelect").select2({
placeholder: "Select Items(s) to CheckOut",
tags: true,
allowClear: true
});
});
</script>
<h1>#ViewData["Title"]</h1>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="CheckOutItems">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="UserId" class="control-label">User ID</label>
<input id="UserId" asp-for="UserId" class="form-control" />
<span asp-validation-for="UserId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Department" class="control-label"></label>
<select asp-for="Department" class="form-control">
<option selected value=""></option>
#foreach (var d in departments)
{
<option>#d.ToString()</option>
}
</select>
<span asp-validation-for="Department" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Role" class="control-label">Role</label>
<select asp-for="Role" class="form-control">
<option selected value=""></option>
#foreach (var r in roles)
{
<option>#r.ToString()</option>
}
</select>
<span asp-validation-for="Role" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Items" class="control-label">Items To Checkout</label>
<select asp-for="Items" class="itemSelect form-control" name="itemss" multiple asp-items="ViewBag.ItemId">
<option value="Select Items(s) To Checkout" disabled></option>
</select>
</div>
<div class="form-group">
<label asp-for="DateCheckedOut" class="control-label" hidden></label>
<input asp-for="DateCheckedOut" class="form-control" hidden />
<span asp-validation-for="DateCheckedOut" class="text-danger" hidden></span>
</div>
<div class="form-group">
<input id="onCheckoutSubmit" type="submit" value="Check Out" class="btn btn-primary" />
</div>
</form>
</div>
</div>
Sorry for the long answer but any help or suggestions are highly appreciated :)
I have asked this questions on other websites too but haven’t received any answers.
I don't see where your Items property is being instantiated, and if it isn't, then it will definitely be null.
You can instantiate it in a constructor:
public class CheckoutItem {
public CheckoutItem(){
Items = new List<string>();
}
}
or directly where you define the property:
public List<string> Items {get; set;} = new List<string>();
On a side note, collections typically do not have setters. Sometimes you need this, but often, only a get is necessary. If you need to "reset" the list, you can use .Clear() and .AddRange().
I have a view that needs to display a drop-down and then displaying data from the drop-down in the same view using viewBag
There is 3 tables customer, assign, employee. Assign and employee have a relationship but the customer does not and is not needed so ViewBag is being used to display data in another view, how I build a drop-down list displayed in the view using the viewBag and display the selected data from the customer table in the same view?
The view that the data is needed to be displayed in mainly the name, task, and image from the URL
#model HandyApp.Models.ViewModels.AsignVM
<div>
// drop down needed in this section
</div>
<div>
// display data from selected drop down item needed in this section
</div>
<form method="post" asp-action="Create">
<div class="container">
<div class="form-row">
<div class="col-md-12">
<h1>Customer task</h1>
</div>
</div>
<div class="form-row">
<div class="col-md-12"><strong style="margin-right: 7px;">Name :</strong><span style="margin-top: 1px;">harry</span></div>
</div>
</div>
<div class="container">
<div class="form-row">
<div class="col-md-12"><strong>Tasks :</strong><span style="margin-left: 12px;">paint shed</span></div>
</div>
</div>
<div class="container">
<div class="form-row">
<div class="col-md-12"><strong>Telephone number :</strong><span style="margin-left: 12px;">000000000000</span></div>
</div>
</div>
<div class="container">
<div class="form-row">
<div class="col"><strong>Address : </strong><span>123 Fake Street</span><span></span></div>
<div class="col-md-12" style="margin-top: 31px;">
<h3 style="margin-left: 0px;">Assign tasks</h3>
</div>
</div>
<div class="form-row">
<div class="col-md-3">
<label style="margin-left: 47px;">Name of customer</label>
<input asp-for="Asign.Name" class="form-control" type="text" value="customers name" style="margin-top: 2px;">
<label style="margin-top: 8px;">Employee Assign </label>
<select asp-for="Asign.EmployeeNameId" asp-items="#Model.TypeDropDown" class="form-control">
<option selected>-- Select option</option>
</select>
<label style="margin-top: 8px;">Employee Assign </label>
<select asp-for="Asign.Status" class="form-control">
<option value="in progress" selected="">in progress</option>
<option value="completed">completed</option>
</select>
</div>
<div class="col-md-3">
<label style="margin-left: 54px;">Tasks </label>
<input asp-for="Asign.Tasks" class="form-control" value="Enter tasks here" style="margin-top: 4px;">
<label style="margin-top: 8px;">Telephone</label>
<input asp-for="Asign.Telephone" value="Type telephone" class="form-control" type="text">
<label tyle="margin-top: 8px;">Address</label>
<input asp-for="Asign.Address" class="form-control" value="enter address" type="text"></div>
</div>
<button class="btn btn-primary" type="submit" style="margin-top: 35px;margin-left: 34px;">Submit</button>
</div>
</form>
Customer model
public class Customer
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Tasks { get; set; }
public string Telephone { get; set; }
public string Address { get; set; }
public string ImageUrl { get; set; }
}
Assign model
public class Assign
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Tasks { get; set; }
public string Telephone { get; set; }
public string Address { get; set; }
public string Status { get; set; }
public string ImageUrl { get; set; }
public int EmployeeNameId { get; set; }
[ForeignKey("EmployeeNameId")]
public virtual Employee Employee { get; set; }
}
Employee model
public class Employee
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Speciality { get; set; }
}
Assign ViewModel
public class AssignVM
{
public Assign Assign { get; set; }
public IEnumerable<SelectListItem> TypeDropDown { get; set; }
}
Assign controller
public class AssignController : Controller
{
private readonly ApplicationDbContext _db;
public AssignController(ApplicationDbContext db)
{
_db = db;
}
public IActionResult Index()
{
IEnumerable<Asign> objList = _db.Assigns;
IEnumerable<Customer> custObj = _db.Customers;
foreach (var obj in objList)
{
obj.Employee = _db.Employees.FirstOrDefault(u => u.Id == obj.EmployeeNameId);
}
ViewBag.Customer = custObj;
return View(objList);
}
public IActionResult Create()
{
AssignVM assignVM = new AssignVM()
{
Assign = new Assign(),
TypeDropDown = _db.Employees.Select(i => new SelectListItem
{
Text = i.Name,
Value = i.Id.ToString()
})
};
return View(assignVM);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(AssignVM obj)
{
_db.Assigns.Add(obj.Assign);
_db.SaveChanges();
return RedirectToAction("Index");
}
public IActionResult Delete(int? id)
{
if (id == null || id == 0)
{
return NotFound();
}
var obj = _db.Assigns.Find(id);
if (obj == null)
{
return NotFound();
}
return View(obj);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult DeletePost(int? id)
{
var obj = _db.Assigns.Find(id);
if (obj == null)
{
return NotFound();
}
_db.Assigns.Remove(obj);
_db.SaveChanges();
return RedirectToAction("Index");
}
}
Use a jquery to get data from controller will be the easiest way, you can check my demo:
The image is stored in wwwroot/Images/*** in my demo.
Controller:
[HttpGet]
public JsonResult GetCustomer(string Id)
{
var img = _db.Customers.Where(x => x.Id.ToString()==Id).ToList();
return Json(img);
}
View:
<div>
<select class="form-control" id="select1" asp-items="#(new SelectList(ViewBag.customers,"Value", "Text"))">
</select>
</div>
<div id="showhere">
</div>
//........your other html
#section Scripts
{
<script>
$(document).ready(function () {
$("#select1").change(function () {
var Id = $("#select1 option:selected").val();
$.ajax({
type: 'Get',
url: 'Assign/GetCustomer',
data: { Id: Id },
dataType: "json",
success: function (data) {
document.getElementById("showhere").innerHTML = "";
document.getElementById("showhere").innerHTML +=
"<img src=" + data[0].imageUrl + " height="+50+" width="+50+">";
}
});
});
});
</script>
}
Result:
The error shows as below:
System.Web.HttpCompileException:
'C:\Users\MEDADUWA\source\repos\CapeXPro\CapeXPro\Views\FAWizard_AddAsset.cshtml(43):
error CS1579: foreach statement cannot operate on variables of type
'FAInfo' because 'FAInfo' does not contain a public definition for
'GetEnumerator''
My ViewModel Look like this:
namespace DAL.Entities
{
public class FAInfo
{
public int WizardId { get; set; }
public string WizardType { get; set; }
public Step2 Step2 { get; set; }
public List<Step2> ListStep2 { get; set; }
public int Status { get; set; }
}
public class Step2
{
public int assetId { get; set; }
public string assetCode { get; set; }
public int assetCategoryId { get; set; }
public int assetTypeId { get; set; }
public int branchId { get; set; }
public int? ccenterId { get; set; }
public string description { get; set; }
public double cost { get; set; }
public double? vat { get; set; }
public double? vatRec { get; set; }
public double? nbt { get; set; }
public double bookValue { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime? ModifiedOn { get; set; }
public string ModifiedBy { get; set; }
public int Status { get; set; }
public InvoiceEntities Invoice { get; set; }
public List<Step2> ListAssets { get; set; }
public List<tbl_assetcategory> ListCategories { get; set; }
public List<tbl_branch> ListBranches { get; set; }
public List<tbl_costcenter> ListDepartments { get; set; }
}
}
This is my Controller:
namespace CapeXPro.Controllers
{
[SessionExpire]
public class FAWizardController : Controller
{
UnitOfWork _unitOfWork = new UnitOfWork();
readonly CommonUtilities _commonService = new CommonUtilities();
#region Main View
FAInfo FAInfoComponent(FAInfo model = null)
{
try
{
//var existjournaldepreciation = _unitOfWork.JournalDepreciationRepository.GetAll(x => x.Id == 1 && x.Status != (int)StatusEnum.Delete).FirstOrDefault();
if (model == null)
{
model = new FAInfo()
{
Status = (int)StatusEnum.Active,
};
}
return model;
}
catch (Exception ex)
{
throw ex;
}
}
// GET: FAWizard
public ActionResult FAWizard()
{
return View("FAWizard", FAInfoComponent());
}
#endregion
#region Add Or Edit Step2
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult Step2(FAInfo AssetData, string BtnPrevious, string BtnNext)
{
try
{
var action = string.Empty;
var before = string.Empty;
var after = string.Empty;
AssetData = FAInfoComponent(AssetData);
if (BtnPrevious != null)
{
FAInfo InvObj = new FAInfo();
InvObj.Step1.InvoiceId = AssetData.Step2.Invoice.InvoiceId;
InvObj.Step1.InvoiceNo = AssetData.Step2.Invoice.InvoiceNo;
InvObj.Step1.PoNo = AssetData.Step2.Invoice.PoNo;
return PartialView("_AddInvoice", InvObj);
}
if (BtnNext != null)
{
if (ModelState.IsValid)
{
var existObj = _unitOfWork.AssetRepository.GetAll(x => x.assetId == AssetData.Step2.assetId && x.Status != (int)StatusEnum.Delete).FirstOrDefault();
if (existObj == null)
{
tbl_asset asset = new tbl_asset()
{
assetId = AssetData.Step2.assetId,
assetCode = AssetData.Step2.assetCode,
assetCategoryId = AssetData.Step2.assetCategoryId,
CreatedBy = System.Web.HttpContext.Current.Session[SessionsEnum.UserId.ToString()].ToString(),
CreatedOn = DateTime.Now,
Status = Convert.ToInt32(AssetData.Status)
};
_unitOfWork.AssetRepository.Insert(asset);
//_unitOfWork.Save();
//int id = department.CcId;
action = ActionType.Insert;
before = null;
after = asset.assetId + "," +
asset.assetCode + "," +
asset.assetCategoryId + "," +
asset.Status + "," +
asset.CreatedBy + "," +
asset.CreatedOn + "," +
asset.ModifiedBy + "," +
asset.ModifiedOn;
}
else
{
FAInfo AssetObj = new FAInfo();
AssetObj.Step2.assetId = AssetData.Step2.assetId;
AssetObj.Step2.assetCode = AssetData.Step2.assetCode;
AssetObj.Step2.assetCategoryId = AssetData.Step2.assetCategoryId;
AssetObj.Step2.ModifiedBy = System.Web.HttpContext.Current.Session[SessionsEnum.UserId.ToString()].ToString();
AssetObj.Step2.ModifiedOn = DateTime.Now;
AssetObj.Step2.Status = Convert.ToInt32(AssetData.Status);
_unitOfWork.AssetRepository.Update(existObj);
action = ActionType.Update;
before = null;
after = existObj.assetId + "," +
existObj.assetCode + "," +
existObj.assetCategoryId + "," +
existObj.Status + "," +
existObj.CreatedBy + "," +
existObj.CreatedOn + "," +
existObj.ModifiedBy + "," +
existObj.ModifiedOn;
}
if (_unitOfWork.Save() > 0)
{
//Update Log Table
AuditLog.SystemLog(Tables.AssetTable, action, before, after);
TempData["message"] = Messages.Success;
ModelState.Clear();
return View("AddDepreciation", new FADepreciationEntities());
}
else
{
TempData["message"] = Messages.Failed;
return PartialView("_AddAsset", AssetData);
}
}
return PartialView("_AddAsset", AssetData);
}
return View();
}
catch (Exception ex)
{
TempData["message"] = Messages.Exception + ex.Message;
return PartialView("_AddAsset", AssetData);
}
}
#endregion
}
}
This is my Partial View
#model DAL.Entities.FAInfo
#using DAL.Enums
#using (Html.BeginForm("Step2", "FAWizard", FormMethod.Post, new { #class = "form-horizontal form-label-left", role = "form", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(m => m.Step2.assetId)
<!-- Editable table -->
<div class="card">
<div class="card-body">
<div id="table" class="table-editable">
<span class="table-add float-right mb-3 mr-2">
<a href="#!" class="text-success">
<i class="fas fa-plus fa-2x" aria-hidden="true"></i>
</a>
</span>
<table id=""
class="table table-striped table-hover table-sm table-bordered text-center">
<thead>
<tr>
<th class="text-center">Line No</th>
<th class="text-center">Asset Code</th>
<th class="text-center">Asset Class</th>
</tr>
</thead>
<tbody>
#foreach (DAL.Entities.FAInfo asset in Model)
{
<tr>
<td>1</td>
<td>#asset.Step2.assetCode</td>
<td>#asset.Step2.ListCategories</td>
<td>
<span class="table-remove">
<button type="button"
class="btn btn-danger btn-rounded btn-sm my-0">
Remove
</button>
</span>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
}
This is my MasterView:
#model DAL.Entities.FAInfo
#using DAL.Enums
#{
ViewBag.Title = "FAWizard";
}
<div class="right_col" role="main">
<div class="full-height">
<div class="clearfix"></div>
<div class="row">
<div class="col-md-12 col-sm-12 col-xs-12">
<div class="x_panel">
<div class="x_title">
<h2>Fixed Assets Capitalization <small>CapeXPro</small></h2>
<div class="clearfix"></div>
</div>
<div class="x_content">
<form class="form-horizontal form-label-left" novalidate>
<p>
For Fixed asset registration - CapeXPro | Union Bank of Colombo
</p>
<span class="section">Fixed Asset Info</span>
<!-- Smart Wizard -->
<p>Proceed with the given steps</p>
<div id="wizard" class="form_wizard wizard_horizontal">
<ul class="wizard_steps">
<li>
<a href="#step-1">
<span class="step_no">1</span>
<span class="step_descr">
Step 1<br />
<small>Invoice and Insurance Details</small>
</span>
</a>
</li>
<li>
<a href="#step-2">
<span class="step_no">2</span>
<span class="step_descr">
Step 2<br />
<small>Asset Details</small>
</span>
</a>
</li>
</ul>
<div id="step-1">
#{Html.RenderPartial("_AddInvoice", Model);}
</div>
<div id="step-2">
#{Html.RenderPartial("_AddAsset", Model);}
</div>
</div>
<!-- End SmartWizard Content -->
</form>
</div>
</div>
</div>
</div>
</div>
</div>
System.Web.HttpCompileException: 'C:\Users\MEDADUWA\source\repos\CapeXPro\CapeXPro\Views\FAWizard_AddAsset.cshtml(43): error CS1579: foreach statement cannot operate on variables of type 'FAInfo' because 'FAInfo' does not contain a public definition for 'GetEnumerator''
This error is thrown because in your partial view FAWizard_AddAsset you're trying to iterate your model like this #foreach (DAL.Entities.FAInfo asset in Model). This assumes that Model is an enumerable of FAInfo, like a List<FAInfo> but apparently it's a FAInfo.
Judging by your code I think there's no multiples of FAInfo, but within your FAInfo there's a List<ListStep2>. If you want to iterate that then change your #foreach into this:
#foreach (DAL.Entities.Step2 asset in Model.ListStep2)
In your #model statement you are using a single instance. This is useful for Details and Edit views of single items. To iterate over entities in a view, you can make the model an IEnumerable of MyClass like so:
#model IEnumerable<DAL.Entities.FAInfo>
I have a List of objects in my Model, how can I make a form for it?
I want to have select box and number input box to add objects and be able to keep adding more before posting form.
If it was just public Cargo cargo I would just make a select box to choose cargo type and input box for amount and that's it. But it's a list so I want to add as much cargo as I want and then post a form. I already have input fields for address (like city, street etc.) in my form but I'm stuck with this list.
Order model (Form model):
public class Order
{
public int Id { get; set; }
public Address PickUpAddress { get; set; }
public Address DropOffAddress { get; set; }
[...]
public List<Cargo> Cargo { get; set; }
}
Cargo model:
public class Cargo
{
public int Id { get; set; }
public int Amount { get; set; }
public CargoType CargoType { get; set; }
}
My solution
I implemented this function manually without any JS code.
The code is very simple. You can refer to my code here directly.
Solving process
We have to insert the order table before we can insert the cargo table. Otherwise, we can't connect the two tables.
We need these three form models.We use the cargocount field to link the two order pages with the cargo page.
public class CargoViewModel
{
public int OrderId { get; set; }
public int Amount { get; set; }
public string CargoType { get; set; }
//Other use
public int CargoCount { get; set; }
public List<CargoViewModel> Cargos { get; set; }
}
public class OrderViewModel
{
public int OrderId { get; set; }
public string PickUpAddress { get; set; }
public string DropOffAddress { get; set; }
public int CargoCount { get; set; }
public List<CargoViewModel> Cargos { get; set; }
}
public class OrdersViewModel
{
public List<OrderViewModel> Orders { get; set; } = new List<OrderViewModel>();
}
When we create an order page, we need to provide the data of cargocount. When we submit the order page, we will save the existing data to the order table, jump to the cargo page, and generate cargocount input tags.
Next, submit the list form.
Submit page code
<form asp-controller="Order" asp-action="CreateCargo" method="post">
#if (Model.CargoCount != 0)
{
for (int itemCount = 0; itemCount < Model.CargoCount; itemCount++)
{
<div class="row">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<div class="form-group" style="width:300px; height:auto; float:left; display:inline">
<label asp-for="#Model.Cargos[itemCount].Amount" class="control-label"></label>
<input asp-for="#Model.Cargos[itemCount].Amount" class="form-control" />
<span asp-validation-for="#Model.Cargos[itemCount].Amount" class="text-danger"></span>
</div>
<div class="form-group" style="width:300px; height:auto; float:left; display:inline">
<label asp-for="#Model.Cargos[itemCount].CargoType" class="control-label"></label>
<input asp-for="#Model.Cargos[itemCount].CargoType" class="form-control" />
<span asp-validation-for="#Model.Cargos[itemCount].CargoType" class="text-danger"></span>
</div>
</div>
</div>
}
}
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
Background data processing code
[HttpPost]
public async Task<IActionResult> CreateCargo(CargoViewModel model)
{
var orderId = await _context.Order.Select(o => o.OrderId).MaxAsync();
var cargos = model.Cargos;
foreach (var item in cargos)
{
var cargo = new Cargo
{
OrderId = orderId,
Amount = item.Amount,
CargoType = item.CargoType
};
await _context.AddAsync(cargo);
await _context.SaveChangesAsync();
}
return RedirectToAction(nameof(Index));
}
Using JS implementation
We need this form models.
public class OrderAndCargoViewModel
{
public int OrderId { get; set; }
public string PickUpAddress { get; set; }
public string DropOffAddress { get; set; }
public List<CargoViewModel> Cargos { get; set; }
}
Next, submit the table form. Submit page code.
<div style="float:right;">
<table id="tb">
<tr>
<th> <label class="control-label">ID</label></th>
<th> <label asp-for="#Model.Cargos.FirstOrDefault().Amount" class="control-label"></label> </th>
<th><label asp-for="#Model.Cargos.FirstOrDefault().CargoType" class="control-label"></label></th>
</tr>
#{
var countId = 0;
for (var itemCount = 0; itemCount < 3; itemCount++)
{
<tr id="trs">
<td>#(++countId)</td>
<td><input asp-for='#Model.Cargos[itemCount].Amount' class= 'form-control' /></td>
<td><input asp-for='#Model.Cargos[itemCount].CargoType' class='form-control' /></td>
</tr>
}
}
</table>
</div>
<input id="btnAdd" value="Add" type="button" class="btn btn-primary" onclick="btnAddClick()">
JS Code.
#section scripts{
<script src="~/js/jquery-3.4.1/jquery-3.4.1.js" type="text/javascript"></script>
<script src="~/js/jquery-3.4.1/jquery-ui-1.12.1.js" type="text/javascript"></script>
<script src="~/js/jquery-3.4.1/jquery.unobtrusive-ajax.js" type="text/javascript"></script>
<script>
var btnAddClick = function () {
var trLen = $("#tb tr[id='trs']").length;
var $lastTr = $("#tb tr[id='trs']").last();
var tr = "<tr id='trs'>";
tr += "<td>" + (trLen + 1) + "</td>";
tr += "<td><input class='form-control' type='number' data-val='true' data-val-required='The Amount field is required.' id='Cargos_"+trLen+"__Amount' name='Cargos["+trLen+"].Amount' value=''></td>";
tr += "<td><input class='form-control' type='text' id='Cargos_"+trLen+"__CargoType' name='Cargos["+trLen+"].CargoType' value=''>";
tr += "</tr>";
$(tr).insertAfter($lastTr);
}
</script>
}
Controller Code.
[HttpPost]
public async Task<IActionResult> CreateOrderAndCargo(OrderAndCargoViewModel model)
{
var order = new Order()
{
PickUpAddress = model.PickUpAddress,
DropOffAddress = model.DropOffAddress
};
await _context.AddAsync(order);
await _context.SaveChangesAsync();
var orderId = await _context.Order.Select(o => o.OrderId).MaxAsync();
var cargos = model.Cargos;
foreach (var item in cargos)
{
var cargo = new Cargo
{
OrderId = orderId,
Amount = item.Amount,
CargoType = item.CargoType
};
await _context.AddAsync(cargo);
await _context.SaveChangesAsync();
}
return RedirectToAction(nameof(Index));
}
Click here to view source codes.
Reference page
About'#'.
JS operation.
It will solve the problem if you use more than one related model in View pages and give a list parameter in actions..
An example;
View;
<input type="text" name="name" id="name1" />
<input type="text" name="name" id="name2" />
Action
public actionresult post(string [] name)
What I'm trying to do--
I have two different database tables (CabinetI, AdminCabinetI). AdminCabinetI has populated data(Column name ItemID) that has to be displayed to users as a dropdownlist. Once users fill out other information, make selections from the dropdownlist and hit the submit button, that data goes to CabinetI.
When I add Dropdownlistfor, it starts throwing an error. I've tried a lot of different ways, but nothing worked. So at this point, I would like to show my code and see what I've done wrong.
This is my ViewModel --
public class MultipleViews
{
public Note note { get; set; }
public AdminCabinetI admincabinetI { get; set; }
public CabinetI cabineti { get; set; }
public IEnumerable<AdminCabinetI> SelectSerialsI { get; set; }
}
This is my Models (AdminCabinetI) and (CabinetI) --
public class AdminCabinetI
{
[Key]
public int ItemNo { get; set; }
[Required(ErrorMessage = "Please enter item title")]
public string ItemName { get; set; }
[Required(ErrorMessage = "Please enter Item Serial number/ID")]
public string ItemID { get; set; }
[Required(ErrorMessage = "Please select cabinet status")]
public string ItemStatus { get; set; }
public string BA { get; set; }
public string Printer { get; set; }
}
public class CabinetI
{
[Key]
public int CabinetNo { get; set; }
[Required]
public string CabinetName { get; set; }
[Required]
public string Department { get; set; }
[Required(ErrorMessage = "Please enter your name")]
public string UserName { get; set; }
[Required(ErrorMessage = "Please select one of cabinet serial numbers")]
public string CabinetSerial { get; set; }
[Required(ErrorMessage = "Please select cabinet status")]
public string CabinetStatus { get; set; }
[Required(ErrorMessage = "Please type specify cabinet location")]
public string CabinetLocation { get; set; }
}
And this is my View --
#model PreMode.ViewModels.MultipleViews
<div class="form-group">
<label>Category</label>
<input type="text" readonly="readonly" class="form-control" style="opacity: 0.6" value="I2" asp-for="cabineti.CabinetName">
</div>
<div class="form-group">
<label>Department</label>
<select class="form-control" asp-for="cabineti.Department">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</div>
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" asp-for="cabineti.UserName" placeholder="Please enter your name" />
<span class="text-danger" asp-validation-for="cabineti.UserName"></span>
</div>
<div class="form-group">
<label>Serial Number</label>
#Html.DropDownListFor(model => model.admincabinetI, new SelectList(Model.admincabinetI.ItemID, "ItemID"), "Select Cabinet Serial #", new { #class = "form-control" })
</div>
<div class="form-group">
<label>Status</label>
<select class="form-control" asp-for="cabineti.CabinetStatus">
<option value="In Use">In Use</option>
<option value="Not In Use">Not In Use</option>
<option value="Testing">Testing</option>
</select>
<span class="text-danger" asp-validation-for="cabineti.CabinetStatus"></span>
</div>
<div class="form-group">
<label>Location</label>
<input type="text" class="form-control" asp-for="cabineti.CabinetLocation" placeholder="Please type current location of the cabinet" />
<span class="text-danger" asp-validation-for="cabineti.CabinetLocation"></span>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Checkout</button>
<a class="btn btn-warning" href="/Cabinet/MainCabinetI">Cancel</a>
</div>
</form>
And this is my Controller--
public IActionResult GetDropDown()
{
if (ModelState.IsValid)
{
using (var db = new DataMigration())
{
var CabinetSerialsI = db.AdminCabinetI.ToList();
var viewModel = new MultipleViews
{
SelectSerialsI = CabinetSerialsI
};
return View(viewModel);
}
}
return View();
}
SelectList doesn't have an overload method that matches your intentions. In HTML land a select element has both values and descriptions, similar to a KeyValuePair. In your case both the key and value are the same. To account for that, try:
SelectList(Model.admincabinetI.ItemID, "ItemID", "ItemID")
Add a constructor to the MultipleViews class and set the variables such as this
public MultipleViews()
{
this.Note = new Note();
this.AdminCabinetI = new AdminCabinetI ();
this.CabinetI = new CabinetI ();
this.SelectSerialsI = new List<AdminCabinetI>();
}
You had not declared the variables before you set their value.