I have a ViewModel that contains two lists of Conditions - BuyConditions and SellConditions - plus a couple of attributes - Name etc. The lists are displayed using tables in the view. jQuery allows the tables to be manipulated - adding Conditions to the tables (from Buy Condition / Sell Condition DDL's) and removing Conditions from the tables.
My problem is that the Condition lists are not updated in the model when it is posted back to the controller.
Something that may point to the issue is that when the model is returned to the view (due to ModelStat.IsValid failing), the data in the Markets DDL still exists, but the data in the Buy and Sell Condition DDL's doesn't.
I can't find an example on the net to figure out where I'm going wrong. Anyone done this before?
ViewModel:
public class StrategyViewModel
{
public string ID { get; set; }
[Display(Name = "Strategy Name")]
public string StrategyName { get; set; }
[Display(Name = "Market")]
public string SelectedMarketID { get; set; }
[Display(Name = "Asset Type")]
public string SelectedShareTypeID { get; set; }
[Display(Name = "Share")]
public string SelectedShareID { get; set; }
public bool Active { get; set; }
public IEnumerable<Market> Markets { get; set; } // top level of three cascading DDL's - the other two populated via JQuery
public IEnumerable<Condition> BuyConditionList { get; set; } // used to populate DDL
public IEnumerable<Condition> SellConditionList { get; set; } // used to populate DDL
public List<BuyCondition> BuyConditions { get; set; } // list of Buy Conditions
public List<SellCondition> SellConditions { get; set; } // list of Sell Conditions
AppRepository repository = new AppRepository();
public StrategyViewModel()
{
// populate lists
Markets = ListUtils.AddDefaultOptionToMarketList( repository.GetMarkets(), -1, "Select a Market" ).AsEnumerable();
BuyConditionList = repository.GetConditions();
SellConditionList = repository.GetConditions();
BuyConditions = new List<BuyCondition>();
SellConditions = new List<SellCondition>();
}
}
Controller:
public ActionResult Create()
{
StrategyViewModel model = new StrategyViewModel();
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "User, Admin")]
public ActionResult Create(StrategyViewModel model)
{
// for debugging
var errorList = ModelState.Values.SelectMany(v => v.Errors);
if (ModelState.IsValid)
{
var user = repository.GetCurrentUser(User.Identity.GetUserId());
var strategy = new Strategy();
strategy.StrategyName = model.StrategyName;
strategy.ShareID = Convert.ToInt32(model.SelectedShareID);
strategy.BuyConditions = model.BuyConditions.ToList();
strategy.SellConditions = model.SellConditions.ToList();
strategy.Active = model.Active;
int strategyID = repository.AddStrategy(user, strategy);
return RedirectToAction("Index");
}
return View(model);
}
View:
#model ShareTrigger.Models.StrategyViewModel
#{
ViewBag.Title = "Create";
}
#{Html.EnableUnobtrusiveJavaScript(true);}
<script type="text/javascript">
$(document).ready(function () {
$(function () {
$('#SelectedMarketID').change(function () {
var selectedMarketID = $(this).val();
$.getJSON('#Url.Action("ShareTypes")', { marketId: selectedMarketID }, function (shareTypes) {
var shareTypesSelect = $('#SelectedShareTypeID');
shareTypesSelect.empty();
$.each(shareTypes, function (index, shareType) {
shareTypesSelect.append($('<option/>').attr('value', shareType.Value).text(shareType.Text));
});
$('#SelectedShareTypeID').trigger("change");
});
});
$('#SelectedShareTypeID').change(function () {
var selectedShareTypeId = $(this).val();
var selectedMarketID = $('#SelectedMarketID').val();
$.getJSON('#Url.Action("Shares")', { shareTypeId: selectedShareTypeId, marketID: selectedMarketID }, function (shares) {
var sharesSelect = $('#SelectedShareID');
sharesSelect.empty();
$.each(shares, function (index, share) {
sharesSelect.append($('<option/>').attr('value', share.Value).text(share.Text));
});
});
});
});
$('#AddBuyCondition').click(function () {
var conditionID = +$("#BuyConditionList").val();
if (conditionID != -2) {
conditionID = +$("#BuyConditionList").val();
var conditionText = $("#BuyConditionList").find('option:selected').text();
$("tr:contains('Add')").remove();
$('#BCDropDownRow').before('<tr class="bcrow"><td class="BuyConditionCell" data-conditionID="' + conditionID + '"><input data-val="true" data-val-number="The field ConditionID must be a number." data-val-required="The ConditionID field is required." id="item_ConditionID" name="item.ConditionID" type="hidden" value="' + conditionID + '">' + conditionText + '</td><td><button class="RemoveBuyCondition type="button" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-minus"></span></button></td></tr>');
$("#BuyConditionList").find('option:selected').remove();
var rows = $('#BuyConditionList option').size();
if (rows == 0) { $("#BuyConditionList").append('<option value="-2">No more conditions to select</option>'); }
}
});
$('#BuyConditionsTable').on('click', '.RemoveBuyCondition', function () {
var conditionID = +$(this).parent().parent().find('.BuyConditionCell').data('conditionid');
var conditionText = $(this).parent().parent().find('.BuyConditionCell').text();
$(this).closest('.bcrow').remove();
$('#BuyConditionList option[value="-2"]').remove();
$("#BuyConditionList").append('<option value="' + conditionID + '">' + conditionText + '</option>');
var options = $('#BuyConditionList option');
var arr = options.map(function (_, o) { return { t: $(o).text(), v: o.value }; }).get();
arr.sort(function (o1, o2) { return o1.t > o2.t ? 1 : o1.t < o2.t ? -1 : 0; });
options.each(function (i, o) {
o.value = arr[i].v;
$(o).text(arr[i].t);
});
});
$('#AddSellCondition').click(function () {
var conditionID = +$("#SellConditionList").val();
if (conditionID != -2) {
conditionID = +$("#SellConditionList").val();
var conditionText = $("#SellConditionList").find('option:selected').text();
$("tr:contains('Add')").remove();
$('#SCDropDownRow').before('<tr class="scrow"><td class="SellConditionCell" data-conditionID="' + conditionID + '"><input id="item_ConditionID" name="item.ConditionID" type="hidden" value="' + conditionID + '">' + conditionText + '</td><td><button class="RemoveSellCondition type="button" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-minus"></span></button></td></tr>');
$("#SellConditionList").find('option:selected').remove();
var rows = $('#SellConditionList option').size();
if (rows == 0) { $("#SellConditionList").append('<option value="-2">No more conditions to select</option>'); }
}
});
$('#SellConditionsTable').on('click', '.RemoveSellCondition', function () {
var conditionID = +$(this).parent().parent().find('.SellConditionCell').data('conditionid');
var conditionText = $(this).parent().parent().find('.SellConditionCell').text();
$(this).closest('.scrow').remove();
$('#SellConditionList option[value="-2"]').remove();
$("#SellConditionList").append('<option value="' + conditionID + '">' + conditionText + '</option>');
var options = $('#SellConditionList option');
var arr = options.map(function (_, o) { return { t: $(o).text(), v: o.value }; }).get();
arr.sort(function (o1, o2) { return o1.t > o2.t ? 1 : o1.t < o2.t ? -1 : 0; });
options.each(function (i, o) {
o.value = arr[i].v;
$(o).text(arr[i].t);
});
});
});
</script>
<h2>Create Strategy</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.StrategyName, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.StrategyName)
#Html.ValidationMessageFor(model => model.StrategyName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SelectedMarketID, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(x => x.SelectedMarketID, new SelectList(Model.Markets, "MarketId", "MarketCode"))
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SelectedShareTypeID, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(x => x.SelectedShareTypeID, Enumerable.Empty<SelectListItem>(), "Select an Asset Type")
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SelectedMarketID, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(x => x.SelectedShareID, Enumerable.Empty<SelectListItem>(), "Select a Share")
</div>
</div>
<div>
</div>
<div class="col-md-10">
<table class="table" id="BuyConditionsTable">
<tr>
<th>
#Html.DisplayName("Buy Conditions")
</th>
<th></th>
</tr>
#foreach (var item in Model.BuyConditions)
{
<tr>
<td>
#Html.HiddenFor(modelItem => item.ConditionID)
#Html.DisplayFor(modelItem => item.ConditionName)
</td>
<td></td>
</tr>
}
<tr id="BCDropDownRow">
<td>
<button id="AddBuyCondition" type="button" class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-plus"></span>
</button>
#Html.DropDownListFor(x => x.BuyConditionList, new SelectList(Model.BuyConditionList, "ConditionID", "ConditionName"))
</td>
<td></td>
</tr>
</table>
</div>
<div>
</div>
<div class="col-md-10">
<table class="table" id="SellConditionsTable">
<tr>
<th>
#Html.DisplayName("Sell Conditions")
</th>
<th></th>
</tr>
#foreach (var item in Model.SellConditions)
{
<tr>
<td>
#Html.HiddenFor(modelItem => item.ConditionID)
#Html.DisplayFor(modelItem => item.ConditionName)
</td>
<td></td>
</tr>
}
<tr id="SCDropDownRow">
<td>
<button id="AddSellCondition" type="button" class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-plus"></span>
</button>
#Html.DropDownListFor(x => x.SellConditionList, new SelectList(Model.SellConditionList, "ConditionID", "ConditionName"))
</td>
<td></td>
</tr>
</table>
</div>
<div class="form-group">
<div class="col-md-offset-9 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
}
The reason you're getting BuyConditions and SellConditions empty because of the following code
#Html.HiddenFor(modelItem => item.ConditionID)
This will render ALL as
<input type="hidden" id="item_ConditionID" name="item.ConditionID" />
It can't be resolved in the controller action Create due to the wrong naming.
Instead, it should have been
#Html.HiddenFor(x => x.SellConditions[index].ConditionID)
This will render the control as (if index is 0)
<input type="hidden" id="SellConditions_0__ConditionID" name="SellConditions[0].ConditionID" />
Therefore, the foreach block should be as follow
#foreach (int index = 0; index < Model.SellConditions.Count; index++)
{
<tr>
<td>
#Html.HiddenFor(x => x.SellConditions[index].ConditionID)
#Html.DisplayFor(x => x.SellConditions[index].ConditionName)
</td>
<td></td>
</tr>
}
And the same rule for BuyConditions too.
Related
I have been trying to create a the ability to add/edit records through the use of a modal in .net core.
I have been trying tutorials such as
https://www.youtube.com/watch?v=QmNtbnUfns8
https://www.mindstick.com/Articles/12723/crud-operation-modal-popup-uses-bootstrap-in-mvc
Neither of these are working for as they are as .net. The modal isnt showing up.
ViewClients.cshtml
#model IEnumerable<Evol.Models.Clients>
#{
ViewData["Title"] = "Clients";
Layout = "~/Views/Shared/_Layout.cshtml";
<div class="card">
<div class="card-header card-header-text card-header-rose">
<div class="card-text">
<h4 class="card-title">Clients</h4>
<p class="card-category"></p>
</div>
</div>
<div class="card-body table-responsive">
<div class="table-responsive">
<table class="table table-hover" id="dataTable" width="100%" cellspacing="0">
<thead class="text-gray">
<tr>
<th>
#Html.DisplayNameFor(model => model.ClientName)
</th>
<th>
Actions
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(model => item.ClientName)
</td>
<td class="text-right">
<i class="material-icons">edit</i>
<button type="button" rel="tooltip" title="Remove" class="btn btn-
danger btn-link btn-sm">
<i class="material-icons">close</i>
</button>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
<div class="modal fade" id="myModal1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
×
<h3 class="modal-title">AddEdit Employee</h3>
</div>
<div class="modal-body" id="myModalBodyDiv1">
</div>
</div>
</div>
</div>
<script>
var EditClient = function (ClientID) {
var url = "/Client/EditClient?ClientID=" + ClientID;
$("#myModalBodyDiv1").load(url, function () {
$("#myModal1").modal("show");
})
}
EditClient.cshmtl (partial view)
#model Evol.Models.Clients
<form id="myForm">
#Html.HiddenFor(m => m.ClientID)
#Html.TextBoxFor(model => model.ClientName, new { #class = "form-control", #placeholder = "Name" })
<a href="#" id="btnSubmit" class="btn btn-success btn-block">
#if (Model.ClientID > 0)
{
<span>Update</span>
}
else
{
<span>Save</span>
}
</a>
</form>
Add Client
<script>
$(document).ready(function () {
$("#btnSubmit").click(function () {
$("#loaderDiv").show();
var myformdata = $("#myForm").serialize();
alert("Success")
$.ajax({
type: "POST",
url: "/Client/ViewClients",
data: myformdata,
success: function () {
$("#loaderDiv").hide();
$("#myModal1").modal("hide");
}
})
})
})
ClientContoller
public IActionResult EditClient(int ClientID)
{
Clients client = new Clients();
if(ClientID > 0)
{
var user = _context.ClientTable.SingleOrDefault(x => x.ClientID == clientID);
client.ClientID = user.ClientID;
client.ClientName = user.ClientName;
}
return PartialView("EditClient", client);
}
}
Did You Created DbContext Class In Your Project?
CRUD Operations In ASP.NET Core Using Entity Framework Core Code First
EF Core DbContext Class Sample
below code just sample for show data and edit or add data to table.
[HttpGet]
public IActionResult AddEditCustomer(long? id)
{
CustomerViewModel model = new CustomerViewModel();
if (id.HasValue)
{
Customer customer = context.Set<Customer>().SingleOrDefault(c => c.Id == id.Value);
if (customer != null)
{
model.Id = customer.Id;
model.FirstName = customer.FirstName;
model.LastName = customer.LastName;
model.MobileNo = customer.MobileNo;
model.Email = customer.Email;
}
}
return PartialView("~/Views/Customer/_AddEditCustomer.cshtml", model);
}
[HttpPost]
public ActionResult AddEditCustomer(long? id, CustomerViewModel model)
{
try
{
if (ModelState.IsValid)
{
bool isNew = !id.HasValue;
Customer customer = isNew ? new Customer
{
AddedDate = DateTime.UtcNow
} : context.Set<Customer>().SingleOrDefault(s => s.Id == id.Value);
customer.FirstName = model.FirstName;
customer.LastName = model.LastName;
customer.MobileNo = model.MobileNo;
customer.Email = model.Email;
customer.IPAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString();
customer.ModifiedDate = DateTime.UtcNow;
if (isNew)
{
context.Add(customer);
}
context.SaveChanges();
}
}
catch (Exception ex)
{
throw ex;
}
return RedirectToAction("Index");
}
This is because you are missing the HTTP Post attribute PLEASE SEE the docs here
https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-3.1
[HTTPPOST]
public IActionResult EditClient(int ClientID)
{
Clients client = new Clients();
if(ClientID > 0)
{
var user = _context.ClientTable.SingleOrDefault(x => x.ClientID == clientID);
client.ClientID = user.ClientID;
client.ClientName = user.ClientName;
}
return PartialView("EditClient", client);
}
}
I made a HttpPost :
[HttpPost]
public IActionResult PokemonDetails(int PokemonId)
{
return PartialView("_PokemonDetails");
}
I want to find all the data from the Id in the http.
the datas are in my controller :
public IActionResult Index()
{
#region ListeDesPokemons
var pokemonList = new List<PokemonModel>();
var Id = 1;
var Img = 1;
pokemonList.Add(new PokemonModel() { Id = Id++, Name = "Bulbizarre", UsName = "Bulbasaur(us)", JpName = "フシギダネ(jp)", Type1 = "Plante", Type2 = "Poison", Rate = 45, Image = "https://eternia.fr/public/media/pokedex/artworks/00" + Img++ + ".png" });
pokemonList.Add(new PokemonModel() { Id = Id++, Name = "Herbizarre", UsName = "Ivysaur(us)", JpName = "フシギソウ(jp)", Type1 = "Plante", Type2 = "Poison", Rate = 45, Image = "https://eternia.fr/public/media/pokedex/artworks/00" + Img++ + ".png" });
#endregion
var model = new PokemonViewModel();
model.Pokemons = pokemonList;
ViewBag.TotalPokemon1G = pokemonList.Count;
return View(model);
}
find good data from id thank you.
I do not have entity yet.
You could use TempData to pass data across different requests .TempData is used to pass data from current request to subsequent request (means redirecting from one page to another). It’s life is very short and lies only till the target view is fully loaded. But you can persist data in TempData by calling Keep() method.
Here is a simple working demo
Model:
public class PokemonModel
{
public int Id { get; set; }
public string Name { get; set; }
public string UsName { get; set; }
public string JpName { get; set; }
public string Type1 { get; set; }
public string Type2 { get; set; }
public int Rate { get; set; }
public string Image { get; set; }
}
public class PokemonViewModel
{
public List<PokemonModel> Pokemons { get; set; }
}
Controller:
public IActionResult PokemonList()
{
#region ListeDesPokemons
var pokemonList = new List<PokemonModel>();
var Id = 1;
var Img = 1;
pokemonList.Add(new PokemonModel() { Id = Id++, Name = "Bulbizarre", UsName = "Bulbasaur(us)", JpName = "フシギダネ(jp)", Type1 = "Plante", Type2 = "Poison", Rate = 45, Image = "https://eternia.fr/public/media/pokedex/artworks/00" + Img++ + ".png" });
pokemonList.Add(new PokemonModel() { Id = Id++, Name = "Herbizarre", UsName = "Ivysaur(us)", JpName = "フシギソウ(jp)", Type1 = "Plante", Type2 = "Poison", Rate = 45, Image = "https://eternia.fr/public/media/pokedex/artworks/00" + Img++ + ".png" });
#endregion
var model = new PokemonViewModel();
model.Pokemons = pokemonList;
var json = JsonConvert.SerializeObject(pokemonList);
TempData["pokemonJson"] = json;
ViewBag.TotalPokemon1G = pokemonList.Count;
return View(model);
}
[HttpPost]
public IActionResult PokemonDetails(int PokemonId)
{
var pokemonJson = TempData["pokemonJson"].ToString();
TempData.Keep("pokemonJson");
var pokemonList = JsonConvert.DeserializeObject<List<PokemonModel>>(pokemonJson);
var pokemon = pokemonList.SingleOrDefault(p => p.Id == PokemonId);
return PartialView("_PokemonDetails",pokemon);
}
View:
#model WebApplication1.Models.PokemonViewModel
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Pokemons[0].Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Pokemons[0].JpName)
</th>
<th>
#Html.DisplayNameFor(model => model.Pokemons[0].UsName)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Pokemons)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.JpName)
</td>
<td>
#Html.DisplayFor(modelItem => item.UsName)
</td>
<td>
<input hidden asp-for="#item.Id" />
PokemonDetails
</td>
</tr>
}
</tbody>
</table>
<div id="pokemon"></div>
#section Scripts{
<script type="text/javascript">
$(".btnclick").click(function () {
var id = $(this).closest("td").find("input").val();
$.ajax({
type: "post",
url: "/Home/PokemonDetails?PokemonId=" + id,
success: function (result) {
$("#pokemon").html(result);
}
});
});
</script>
}
PartialView
#model WebApplication1.Models.PokemonModel
<div>
<hr />
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.Id)
</dt>
<dd>
#Html.DisplayFor(model => model.Id)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Name)
</dt>
<dd>
#Html.DisplayFor(model => model.Name)
</dd>
<dt>
#Html.DisplayNameFor(model => model.JpName)
</dt>
<dd>
#Html.DisplayFor(model => model.JpName)
</dd>
<dt>
#Html.DisplayNameFor(model => model.UsName)
</dt>
<dd>
#Html.DisplayFor(model => model.UsName)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Type1)
</dt>
<dd>
#Html.DisplayFor(model => model.Type1)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Type2)
</dt>
<dd>
#Html.DisplayFor(model => model.Type2)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Rate)
</dt>
<dd>
#Html.DisplayFor(model => model.Rate)
</dd>
</dl>
</div>
You can use LINQ to query the list for the Id you want.
int PokemonId = 2; // input from http post
var result = pokemonList.FirstOrDefault(p => p.Id == PokemonId);
Ok I made it here is the answer.
My controller:
public IActionResult Index()
{
#region ListeDesPokemons
var pokemonList = new List<PokemonModel>();
var Id = 1;
var Img = 1;
pokemonList.Add(new PokemonModel() { Id = Id++, Name = "Bulbizarre", UsName = "Bulbasaur(us)", JpName = "フシギダネ(jp)", Type1 = "Plante", Type2 = "Poison", Rate = 45, Image = "https://eternia.fr/public/media/pokedex/artworks/00" + Img++ + ".png" });
pokemonList.Add(new PokemonModel() { Id = Id++, Name = "Herbizarre", UsName = "Ivysaur(us)", JpName = "フシギソウ(jp)", Type1 = "Plante", Type2 = "Poison", Rate = 45, Image = "https://eternia.fr/public/media/pokedex/artworks/00" + Img++ + ".png" });
var model = new PokemonViewModel();
model.Pokemons = pokemonList;
var json = JsonConvert.SerializeObject(pokemonList);
TempData["pokemonListJson"] = json;
TempData.Keep("PokemonListJson");
ViewBag.TotalPokemon1G = pokemonList.Count;
return View(model);
}
[HttpPost]
public IActionResult PokemonDetails(int pokemonId)
{
if (TempData["pokemonListJson"] != null)
{
if (string.IsNullOrEmpty(TempData["pokemonListJson"].ToString()))
{
return null;
}
}
var pokemonListJson = TempData["pokemonListJson"].ToString();
TempData.Keep("PokemonListJson");
var pokemonList = JsonConvert.DeserializeObject<List<PokemonModel>>(pokemonListJson);
var selectedPokemon = pokemonList.SingleOrDefault(p => p.Id == pokemonId);
if (selectedPokemon != null)
{
return PartialView("_PokemonDetails", selectedPokemon);
}
return null;
}
My partial View:
#model PokemonModel
<div id="taillDescriptionModal" class="modal-dialog modal-dialog-scrollable mw-100 m-auto" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 id="modalLabelStack2" class="modal-title font-weight-bold float-left">n° #Html.DisplayFor(model => model.Id)</h5>
<div id="nomPokemonStack2" class="ml-auto">
<h5 id="Name">#Html.DisplayFor(model => model.Name)</h5> <h5 id="UsName">#Html.DisplayFor(model => model.UsName)</h5> <h5 id="JpName">#Html.DisplayFor(model => model.JpName)</h5>
</div>
<button type="button" class="close" data-dismiss="modal" aria-label="close">
<span class="text-danger" aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col overflow-hidden">
<img class="img-fluid rounded-lg" src="#Html.DisplayFor(model => model.Image)" alt="pokemon.Name" />
</div>
<div class="col">
<span>Type : </span>
<div class="col text-white">
<span class="#Html.DisplayFor(model => model.Type1) badge">#Html.DisplayFor(model => model.Type1)</span>
<span class="#Html.DisplayFor(model => model.Type2) badge">#Html.DisplayFor(model => model.Type2)</span>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Fermer</button>
<button type="submit" class="btn btn-success" onclick="afficheIdSurIndex(#Html.DisplayFor(model => model.Rate))"> Choisir</button>
</div>
</div>
</div>
<script>
function afficheIdSurIndex(selectedPokemonRate) {
$.ajax({
url: '/Pokedex/Calcul/',
type: 'POST',
dataType: "html",
data: { "selectedPokemonRate": selectedPokemonRate },
success: function () {
//enlever la classe pour afficher le contenu de la div
$('#Test').removeClass('text-hide');
//$('#Test').addClass('text-show');
var rateTxt = 'Taux de Capture du pokémon sélectionné : ' + selectedPokemonRate
//vider le contenu de la div
$("#Test").empty();
//écrire dans la div
$("#Test").append(rateTxt);
//fermer les modals
$('#pokemonDetails').modal('hide');
$('#choixPokemon').modal('hide');
}
})
}
</script>
My Index page:
#model PokemonViewModel
#{
ViewData["Title"] = "Pokedex";
Layout = "~/Views/Shared/_LayoutPokemon.cshtml";
<script src="~/lib/jquery/dist/jquery.min.js"></script>
}
<h1>Pokedex</h1>
<!-- Button choix Pokémon modal -->
<div class="container">
<button type="button" class="btn btn-primary mb-2" data-toggle="modal" data-target="#choixPokemon">
Pokemon 1G
</button>
</div>
<!-- Modal choix Pokémon -->
<div id="choixPokemon" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="choixPokemonModalLabel" aria-hidden="true">
<div id="modalWitdh" class="modal-dialog modal-dialog-scrollable mw-100 m-auto" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 id="choixPokemonModalLabel" class="modal-title">Pokédex première génération, #ViewBag.TotalPokemon1G Pokémons </h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body text-center">
<div class="row">
#foreach (var pokemon in Model.Pokemons)
{
<div class="col">
<button type="submit" class="btn" onclick="getInfo(#pokemon.Id)">
<div class="card text-center rounded-lg">
<div id="tailleCard" class="card-body">
<h5 id="cardTitle" class="card-title">n°#pokemon.Id <br /> #pokemon.Name</h5>
<img id="tailleImg" src="#pokemon.Image" alt="#pokemon.Name" />
</div>
</div>
</button>
</div>
}
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Fermer</button>
</div>
</div>
</div>
</div>
<!-- Modal Description du pokémon choisi -->
<div id="pokemonDetails" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="descriptionPokemonModalLabel" aria-hidden="true">
#*Contenue dans vu partiel _PokemonDetails*#
</div>
#*Div de collection des donnés du pokémon selectionné dans le deuxième modal.(données provenant de la vue partiel _PokemonDetails) *#
<div class="row">
<div class="col">
<h6 id="Test" class="text-hide"></h6>
</div>
</div>
#*button script pour collecter les données du pokémon sélectionné dans le 1er modal*#
<script>
function getInfo(pokemonId) {
event.preventDefault;
console.log(pokemonId);
$.ajax({
url: '/Pokedex/PokemonDetails/',
type: 'POST',
dataType: "html",
data: { "pokemonId": pokemonId },
success: function (response) {
$("#pokemonDetails").html(response);
$('#pokemonDetails').modal('show');
}
})
}
</script>
In the startup page I need to add:
services.AddMemoryCache();
services.AddSession();
services.AddMvc().AddSessionStateTempDataProvider();
I put everything here for help anyone who need help.
add a breakpoint in action PokemonDetails:
[HttpPost]
public IActionResult PokemonDetails(int pokemonId)
{ // add break point here
when the break point is hit here, did you get pokemonId ?
I'm working on a page that will add the selected item from a dropdownlist to a List<> using button onclick.
The problem is the new selecteditem is overwriting the old value.
I simply would like to display a table from the selected items like this:
#---Model-----Remove-----
1 Model#1 x
2 Model#2 x
3 Model#3 x
4 Model#4 x
5 Model#5 x
-------------------------
Please see my code below,
ModelDescription.cs (model):
public class ModelDescription
{
public string modelDesc { get; set; }
}
method in controller:
public ActionResult StockOnHand()
{
bindModelDesc();
return View();
}
public void bindModelDesc()
{
var mc = db.ModelMaster_tbl.ToList();
List<SelectListItem> mclist = new List<SelectListItem>();
mclist.Add(new SelectListItem { Text = "--Select Model Type--", Value = "0" });
mclist.Add(new SelectListItem { Text = "--Select All Model--", Value = "1" });
foreach (var m in mc.Select(x => x.modelDesc).Distinct())
{
mclist.Add(new SelectListItem { Text = m, Value = m });
ViewBag.ModelDescs = mclist;
}
}
public ActionResult AddToListSOH(ModelDescription model)
{
var result = new List<ModelDescription>();
var res = db.ModelMaster_tbl.Where(x => x.modelDesc == model.modelDesc).SingleOrDefault();
result.Add(new ModelDescription { modelDesc = res.modelDesc });
return PartialView("AddToListSOH", result);
}
StockOnHand.cshtml (view):
#using (Html.BeginForm("StockOnHand", "PWSupermarket", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<div class="card">
<div class="card-body">
<form class="form-horizontal" role="form">
<h5 class="card-title">Stock On Hand</h5>
<p class="card-text">Generates the buildable quantity of a unit. </p>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#if (TempData["Message"] != null)
{
<span class="text-success"><strong>#TempData["Message"]</strong></span>
}
<div class="form-group">
#Html.LabelFor(model => model.modelDesc, htmlAttributes: new { #class = "col-md-3 control-label" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.modelDesc, ViewBag.ModelDescs as List<SelectListItem>, htmlAttributes: new { #class = "form-control" })
<button class="btn btn-outline-primary mt-1" type="button" onclick="AddToList()">Add To List</button>
</div>
</div>
<div id="foo1" class="mt-2">
</div>
</form>
</div>
</div>
}
Javascript to render the list of selected items partial view:
<script type="text/javascript">
function AddToList() {
$.ajax({
type: "Get",
url: '#Url.Action("AddToListSOH", "PWSupermarket")',
data: { modelDesc: $('#modelDesc').val() },
contentType: "application/html; charset=utf-8",
success: function (result) {
$('#foo1').html(result);
},
error: function (ex) { alert('failed.'); }
})
}
</script>
AddToListSOH.cshtml (Partial View for the list of selected items):
#model IEnumerable<MESProject_P1_csmvc.Models.ModelDescription>
<div>
#{ var count = 0;}
<table class="table table-sm table-striped" #*style="font-size: .7rem;"*#>
<caption>List of Models</caption>
<thead class="thead-dark">
<tr>
<th>#</th>
<th>Model</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#count
</td>
<td>
#Html.DisplayFor(i => item.modelDesc)
</td>
</tr>
}
</tbody>
</table>
</div>
screen shot of the page
Example to make SelectListItem List
private List<SelectListItem> ModelDeskList(ModelDesk modelDesc)
{
List<SelectListItem> selectList = new List<SelectListItem>();
selectList.Add(new SelectListItem { Value = "", Text = "------Select-----",Selected=true });
foreach (var model in modelDesc)
{
selectList.Add(new SelectListItem { Value = model.Id.ToString(), Text = model.Name});
}
return selectList;
}
I hope you find your solution from it
I solved my problem thanks to this link:
I'm storing the list of emails in Session["emails"] and every time I add a new email to the list, I just update it a pass it to a new list with all the records and at the end return the partial view.
.NET use partial view multiple times #Rolando F
I've changed some of my codes:
ModelDescription.cs
public class ModelDescription
{
public IEnumerable<string> modelsAdded { get; set; }
}
AddToListSOH method in controller:
public ActionResult AddToListSOH(string model)
{
if (Session["modelInputs"] == null)
{
List<string> temphandler1 = new List<string>();
temphandler1.Add(model);
Session["modelInputs"] = temphandler1;
}
else
{
List<string> temphandler2 = new List<string>();
temphandler2 = (List<string>)Session["modelInputs"];
temphandler2.Add(model);
Session["modelInputs"] = temphandler2;
}
var result = new ModelDescription { modelsAdded = (List<string>)Session["modelInputs"] };
return PartialView("AddToListSOH", result);
}
AddToListSOH.cshtml (Partial View):
<table class="table table-sm table-striped" #*style="font-size: .7rem;"*#>
<caption>List of Models</caption>
<thead class="thead-dark">
<tr>
<th>#</th>
<th>Model</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.modelsAdded)
{
<tr>
<td>
#count
</td>
<td>
#Html.DisplayFor(i => item)
</td>
<td>
Remove
</td>
</tr>
}
</tbody>
</table>
I am trying to create a system where it is possible to add/ change device configurations. The user should be able to add / delete rows at the same time.
Everytime a config is saved, a new config_id is created and VersionNr is increased.
I am 100% sure I am doing something wrong, and what is going wrong. But I dont know how to fix it or improve it.
Here is my code:
public ActionResult Edit(int? Id)
{
//create new list
var Device_Pricelist = new List<Device_Pricelist>(db.Device_Pricelist.Where(r => r.DeviceConfig.Device_config_id == Id));
//create new SelectList in Device_Pricelist
var SelectedCMI = (from d in db.pricelist
select new { d.Price_id, Value = d.bas_art_nr }).Distinct();
//call viewbag based on SelectedCMI query
ViewBag.SelectedCMI = new SelectList(SelectedCMI.Distinct(), "Price_id", "Value");
return View(Device_Pricelist);
}
public ActionResult Edit([Bind(Include = "id,Device_config_id,Price_id,amount,assembly_order")]DeviceConfig deviceConfig, List<Device_Pricelist> device_Pricelists)
{
if (ModelState.IsValid)
{
try
{
try
{
db.DeviceConfig.Add(deviceConfig).Device_config_id = deviceConfig.Device_config_id++;
db.DeviceConfig.Add(deviceConfig).device_type_id = deviceConfig.device_type_id = 13;
db.DeviceConfig.Add(deviceConfig).Active = true;
//Needs to be based on current VersionNr in deviceConfig
db.DeviceConfig.Add(deviceConfig).VersionNr = deviceConfig.VersionNr + 1;
db.DeviceConfig.Add(deviceConfig).Date = deviceConfig.Date = DateTime.Now;
}
finally
{
foreach (var item in device_Pricelists)
{
db.Entry(item).State = EntityState.Added;
}
}
db.SaveChanges();
TempData["SuccesMessage"] = "Data is Succesfully saved";
return RedirectToAction("Index");
}
catch
{
TempData["AlertMessage"] = "Saving Data Failed, " + "Try Again";
}
}
return View(device_Pricelists);
}
view:
#model List<ConcremoteDeviceManagment.Models.Device_Pricelist>
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm("Edit", "Home", FormMethod.Post))
{
<h1>
#Html.DisplayName("Edit Configuration")
</h1>
<h2>
#* #Html.DisplayFor(model => model.DeviceType.name)<br />*#dammit
</h2>
if (TempData["AlertMessage"] != null)
{
<p class="alert alert-danger" id="FailMessage">#TempData["AlertMessage"]</p>
}
#Html.ValidationSummary(true)
#Html.AntiForgeryToken()
<div>
#* Add New*#
</div>
<table class="table table-hover" id="dataTable">
<tr>
<th class="table-row">
#Html.DisplayName("BAS artikelnummer")
</th>
<th class="table-row">
#Html.DisplayName("Beschrijving")
</th>
<th class="table-row">
#Html.DisplayName("Aantal")
</th>
<th class="table-row">
#Html.DisplayName("Bouw Volgorde")
</th>
<th class="table-row">
Add New Row
</th>
</tr>
#if (Model != null && Model.Count > 0)
{
int j = 0;
foreach (var item in Model)
{
<tr>
#Html.HiddenFor(a => a[j].id)
#Html.HiddenFor(a => a[j].Device_config_id)
#* #Html.HiddenFor(a => a[j].Price_id)*#
<td class="table-row">
#Html.DropDownListFor(a => a[j].Price_id, (IEnumerable<SelectListItem>)ViewBag.SelectedCMI, null, new { #class = "form-control" })
</td>
<td class="table-row">
#Html.DisplayFor(a => a[j].Pricelist.description, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(a => a[j].Pricelist.description, "", new { #class = "text-danger" })
</td>
<td class="table-row">
#Html.EditorFor(a => a[j].amount, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(a => a[j].amount, "", new { #class = "text-danger" })
</td>
<td class="table-row">
#Html.EditorFor(a => a[j].assembly_order, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(a => a[j].assembly_order, "", new { #class = "text-danger" })
</td>
#*<td class="table-row">
#Html.DisplayFor(a => a[j].DeviceConfig.Date, new { htmlAttributes = new { #class = "form-control" } })
</td>*#
<td>
#if (j > 0)
{
Remove
}
</td>
</tr>
j++;
}
}
</table>
<input type="submit" value="Save Device Data" class="btn btn-primary" />
<button onclick="location.href='#Url.Action("Index", "Home")';return false; " class="btn btn-primary">Back to list</button>
}
#section Scripts{
#*#Scripts.Render("~/bundles/jqueryval")*#
<script language="javascript">
$(document).ready(function () {
//1. Add new row
$("#addNew").click(function (e) {
e.preventDefault();
var $tableBody = $("#dataTable");
var $trLast = $tableBody.find("tr:last");
var $trNew = $trLast.clone();
var suffix = $trNew.find(':input:first').attr('name').match(/\j+/);
$trNew.find("td:last").html('Remove');
$.each($trNew.find(':input'), function (i, val) {
// Replaced Name
var oldN = $(this).attr('name');
var newN = oldN.replace('[' + suffix + ']', '[' + (parseInt(suffix) + 1) + ']', '[' + suffix + ']', '[' + (parseInt(suffix) + 1) + ']', '[' + suffix + ']', '[' + (parseInt(suffix) + 1) + ']');
$(this).attr('name', newN);
//Replaced value
var type = $(this).attr('type');
//if (type.toLowerCase() == "text") {
// $(this).attr('value', '');
//}
// If you have another Type then replace with default value
$(this).removeClass("input-validation-error");
});
$trLast.after($trNew);
// Re-assign Validation
//var form = $("form")
// .removeData("validator")
// .removeData("unobtrusiveValidation");
//$.validator.unobtrusive.parse(form);
});
// 2. Remove
//$('a.remove').live("click", function (e) { --> this is for old jquery library
$('body').on("click", '#remove', function (e) {
e.preventDefault();
$(this).parent().parent().remove();
});
});
</script>
<script type="text/javascript">
function SelectedIndexChanged() {
//Form post
document.demoForm.submit();
}
</script>
I hope somebody is able to help me.
More information will be given when needed.
Your method accepts 2 parameters but you are only posting 1 object - List<Device_PriceList>. Let's assume you want to construct a new DeviceConfig based on the existing one, you should change your Action method to the following:
public ActionResult Edit(List<Device_Pricelist> device_Pricelists)
{
if (ModelState.IsValid)
{
try
{
var deviceConfig = db.DeviceConfig.Find(device_Pricelists.First().Device_config_id);
deviceConfig.device_type_id = 13;
deviceConfig.Active = true;
deviceConfig.VersionNr++;
deviceConfig.Date = DateTime.Now;
db.DeviceConfig.Add(deviceConfig);
foreach(var item in device_Pricelists)
{
item.Device_config_id = deviceConfig.Device_config_id;
}
db.Device_Pricelists.AddRange(device_Pricelists);
db.SaveChanges();
TempData["SuccesMessage"] = "Data is Succesfully saved";
return RedirectToAction("Index");
}
catch
{
TempData["AlertMessage"] = "Saving Data Failed, Try Again";
}
}
return View(device_Pricelists);
}
Remember when posting a list, you need to post complete sets of the object you're trying to map to. That is for example [0].Id, [0].Device_config_id (etc), [1].Id, [1].Device_config_id (etc).
Your JS doesn't seem correct, particularly the .replace(..) call with 6 parameters, so you're probably seeing lots of [0]s when you clone the rows. Some simpler JS that will get you the same result is:
var oldN = $(this).attr('name');
var idx = parseInt(oldN.substr(1, oldN.indexOf(']')));
var newN = oldN.replace('[' + idx + ']', '[' + (idx + 1) + ']');
When I am using this code as web view, it works fine, but when with developer option in Chrome I select Mobile View, FormCollection shows empty strings in the controller
VIEW (Edit updtaed)
<div class="page product-details-page deal-product-details-page">
#using (Html.BeginForm("AddProductToCart_Details", "DealProduct", new { productId = Model.Id, shoppingCartTypeId = 1 }, FormMethod.Post))
{
<div class="page-body">
#using (Html.BeginRouteForm("Product", new { SeName = Model.SeName }, FormMethod.Post, new { id = "product-details-form" }))
{
#{
var dataDictAttributes = new ViewDataDictionary();
dataDictAttributes.TemplateInfo.HtmlFieldPrefix = string.Format("attributes_{0}", Model.Id);
#Html.Partial("~/Views/Product/_ProductAttributes.cshtml", Model.ProductAttributes, dataDictAttributes)
}
<!--gift card-->
#{
var dataDictGiftCard = new ViewDataDictionary();
dataDictGiftCard.TemplateInfo.HtmlFieldPrefix = string.Format("giftcard_{0}", Model.Id);
#Html.Partial("~/Views/Product/_GiftCardInfo.cshtml", Model.GiftCard, dataDictGiftCard)
}
<!--rental info-->
#{
var dataDictRental = new ViewDataDictionary();
dataDictRental.TemplateInfo.HtmlFieldPrefix = string.Format("rental_{0}", Model.Id);
#Html.Partial("~/Views/Product/_RentalInfo.cshtml", Model, dataDictRental)
}
<!--price & add to cart-->
#{
var dataDictPrice = new ViewDataDictionary();
dataDictPrice.TemplateInfo.HtmlFieldPrefix = string.Format("price_{0}", Model.Id);
#Html.Partial("~/Views/Product/_ProductPrice.cshtml", Model.ProductPrice, dataDictPrice)
#Html.Partial("~/Views/Product/_ProductTierPrices.cshtml", Model.TierPrices)
}
<!--wishlist, compare, email a friend-->
<!--attributes-->
#{
var item = #Model.AssociateProductAttributesList.Where(x => x.Item1 == data.Id).Select(x => x.Item2).ToList()[0];
bool isAttributes =false;
}
<div class="popup" data-popup="popup-#data.Id">
<div class="popup-inner">
<h2>#data.Name</h2>
<p>#data.ShortDescription</p>
<br />
#foreach (System.Collections.DictionaryEntry value in item)
{
var val = data.Id + "_" + value.Key.ToString();
isAttributes = true;
#*<div class="attributes">*#
<dl>
<dt id="product_attribute_label_19">
<label class="text-prompt">
#value.Key.ToString()
</label>
</dt>
<dd id="product_attribute_input_19" class="product_attribute_inputdiv_#val">
#Html.DropDownList("Attributes," + data.Id + "," + value.Key.ToString(), new SelectList((System.Collections.IEnumerable)value.Value, "Id", "Name"), "--- Please select ---")
</dd>
</dl>
#*</div>*#
}
<br />
<div onclick="ImageBlur('div_#data.Id')" class="buttons" style="text-align:left;">
<input class="button-1" data-popup-close="popup-#data.Id" type="button" value="Add to back" />
</div>
<a class="popup-close" data-popup-close="popup-#data.Id" href="#">x</a>
</div>
</div>
#if (item.Count == 0)
{
#Html.Hidden("Attributes," + data.Id + ",", "0")
<div class="popup" data-popup="popup-#data.Id">
<div class="popup-inner">
<h2>#data.Name</h2>
<p>#data.ShortDescription</p>
<div onclick="ImageBlur('div_#data.Id')" class="buttons" style="text-align:left;">
<input class="button-1" data-popup-close="popup-#data.Id" type="button" value="Add to back" />
</div>
<a class="popup-close" data-popup-close="popup-#data.Id" href="#">x</a>
</div>
</div>
}
#if (isAttributes)
{
<a style="color: blue;" data-popup-open="popup-#data.Id" href="#">
<img id="imgdiv_#data.Id" src="~/Themes/Playground/Content/img/dealselectattribut.png" class="select-atr-img" style="width: 50%; margin-bottom: 10px;"/>
</a>
}
</div>
}
</div>
<div>
</div>
#{
var dataDictAddToCart = new ViewDataDictionary();
dataDictAddToCart.TemplateInfo.HtmlFieldPrefix = string.Format("addtocart_{0}", Model.Id);
<div class="overview" style="width:100%; margin-left:auto">
#Html.Partial("~/Views/Product/_AddToCart.cshtml", Model.AddToCart, dataDictAddToCart)
</div>
}
</div>
}
</div>
}
</div>
Controller
public ActionResult AddProductToCart_Details(int productId, int shoppingCartTypeId, FormCollection form)
{
if (_productService.IsDealProducts(productId))
{
if (!IsCompleteSelected(form))
{
return Json(new
{
success = false,
message = " Plese select all associated product attribute "
});
}
}
//more code here
}
Normal View (Web View)
Mobile View
Form in form is not allowed. This is your issue.