Database value not populating on button submit - c#

When I click the submit button on my form the value of Submit is not displaying and at the same time my input fields at the top are still not autofilling like I'd like them to. I'm also trying to use the eye icon to hide the value on post request and clicking the eye icon will reveal the value on textbox.
index.cshtml
#page "{id?}"
#model IndexModel
#{ViewData["Title"] = "Main";}
<div class=" container">
<div class="row">
<div class="text-center">
<h1 class="display-4">#Model.PageTitle</h1>
</div>
</div>
<div class="row">
<form class="mt-0" method="get">
<div class="row">
<div class="col-3 offset-2" id="DepartmentResult"></div>
<div class="col-4" id="EmployeeResult"></div>
</div>
</form>
<form class="mt=0" method="post">
<div class="row">
<label class="col-2 offset-3 col-form-label">Employee Name:</label>
<div class="col-2">
<input class="form-control" title="Employee name" asp-for="Name">
</div>
</div>
<br />
<div class="row">
<label class="col-2 offset-3 col-form-label">Department Name:</label>
<div class="col-2">
<input class="form-control" title="Department name" asp-for="DeptName">
</div>
</div>
<br />
<div class="row">
<button class="btn btn-outline-dark col-1 offset-5" type="submit" id="SubmitBtn" name="SubmitBtn" value="Submit" asp-page-handler="Submit">Submit</button>
</div>
<br />
<div class="row">
<div col-4>
<br />
<div class=" row">
<label class="col-6 col-form-label">Social Security #:</label>
<div class="col-5">
<input class="form-control" type="text" asp-for="OutputSSN" disabled />
<i class="fa fa-eye-slash"></i>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
#section Scripts {
<script>
$(document).ready(function()
{
$.ajax(
{
url: "/Index?handler=DisplayDepartment",
type: "GET",
data: { value: #Model.Id },
headers: { RequestVerificationToken: $('input:hidden[name="__RequestVerificationToken"]').val() },
success: function(data) { $("#DepartmentResult").html(data); }
});
});
</script>
}
index.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using PracticeApp.Models;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading.Tasks;
// Namespaces
namespace PracticeApp.Pages
{
// Classes
public class IndexModel : PageModel
{
// Fields
public CompanyContext _context;
// Properties
[BindProperty(SupportsGet = true)] public int Id { get; set; }
[BindProperty] public string PageTitle { get; set; } = "Employee Check";
public Employee CheckEmployee { get; set; }
[BindProperty, DataMember] public string Name { get; set; }
[BindProperty, DataMember] public string DeptName { get; set; }
public string OutputSSN { get; set; }
// Constructors
public IndexModel(CompanyContext context) { _context = context; }
// Methods
public PartialViewResult OnGetDisplayDepartment(int value) => Partial("_DisplayDepartmentPartial", _context.Departments.Where(x => x.DepartmentId == value).ToList());
public PartialViewResult OnGetDisplayEmployee(string value) => Partial("_DisplayEmployeePartial", _context.Employees.Where(x => x.DepartmentName == value).GroupBy(x => x.EmployeeName).Select(x => x.First()).ToList());
public async Task<IActionResult> OnPostSubmit()
{
OutputSSN = $"{SubstringCheck(OutputSSN, 3)}-{SubstringCheck(OutputSSN, 3, 2)}-{SubstringCheck(OutputSSN, 5, 4)}";
return Page();
}
public string SubstringCheck(string s, int length)
{
int len = s.Length;
if (len > length)
{
len = length;
}
return s.Substring(0, len);
}
public string SubstringCheck(string s, int b, int length)
{
int len = s.Length;
if (len <= b)
{
return s;
}
len -= b;
if (len > length)
{
len = length;
}
return s.Substring(b, len);
}
}
}

You forgot to add a BindProperty attribute to your OutputSSN property, so the posted form value is not being bound to it. That's why you get a NullReferenceException when you try to access its Length property.
[BindProperty] public string OutputSSN { get; set; }

As #Mike Brind has said the posted form value is not being bound to it.
First you need to add [BindProperty] like this:
[BindProperty] public string OutputSSN { get; set; }
Besides,
<input class="form-control" type="text" asp-for="OutputSSN" disabled />
you set the input disabled , so it will cause form value is not being bound to it too. If you want it cannot be modified, you can use readonly:
<input class="form-control" type="text" asp-for="OutputSSN" readonly />
I'm also trying to use the eye icon to hide the value on post request
and clicking the eye icon will reveal the value on textbox.
Below is a demo about eye icon, you can refer to it, I set the value to OutputSSN to show data , you can use your way:
<input class="form-control" asp-for="OutputSSN" value="a" type="text" readonly/>
<i class="far fa-eye" id="toggleOutputSSN" ></i>
#section Scripts {
<script>
$(document).ready(function()
{
$.ajax(
{
url: "/Index?handler=DisplayDepartment",
type: "GET",
data: { value:#Model.Id },
headers: { RequestVerificationToken: $('input:hidden[name="__RequestVerificationToken"]').val() },
success: function(data) { $("#DepartmentResult").html(data); }
});
const toggleOutputSSN = document.querySelector('#toggleOutputSSN');
const OutputSSN = document.querySelector('#OutputSSN');
toggleOutputSSN.addEventListener('click', function (e) {
// toggle the type attribute
const type = OutputSSN.getAttribute('type') === 'text' ? 'password' : 'text';
OutputSSN.setAttribute('type', type);
// toggle the eye slash icon
this.classList.toggle('fa-eye-slash');
});
});
</script>
}
result:

Related

How to get ID of value in Autocomplete texbox in ASP

I am getting list of Geolocations using autocomplete , after choosing one willing to get ID of chosen values in Textboxs and set it to hidden controls. No idea how to do it.
My codes are as follow :
index.cshtml:
`<script>
$(document).ready(function () {
$('#ToLocation').autocomplete({
source: '#Url.Page("index", "search")'
});
});
</script>
<script>
$(document).ready(function () {
$('#FromLocation').autocomplete({
source: '#Url.Page("index", "search")'
});
});
<div class="row">
<div class="col">
From
<input class="form-control" id="FromLocation">
<input type="hidden" id="hfFromLocationID" name="FromLocationId"/>
</div>
<div class="col">
To
<input class="form-control" id="ToLocation">
<input type="hidden" id="hfToLocationID" name="ToLocationId"/>
</div>
</div>`
index.cshtml.cs:
`public IActionResult OnGetSearch(string term)
{
var names = context.GeoLocations.Where(p => p.GeoLocationName.Contains(term)).Select(p => p.GeoLocationName ).ToList();
return new JsonResult(names);
}`
GeoLocation.cs
`public class GeoLocation
{
public int Id { get; set; }
public string GeoLocationName { get; set; }
}`

why is my foreign key model not validating?

Having started studying asp net core 6, I ran into the problem of invalidity of my model.
What is the hidden problem?
Model of Product
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TestWebApplication.Models
{
public class Product
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
[Range(0.1, int.MaxValue)]
public double Price { get; set; }
public string Image { get; set; }
[Display(Name = "Category Type")]
public int CategoryId { get; set; }
[ForeignKey("CategoryId")]
public virtual Category Category { get; set; }
}
}
Model of ProductVM
using Microsoft.AspNetCore.Mvc.Rendering;
namespace TestWebApplication.Models.ViewModels
{
public class ProductVM
{
public Product Product { get; set; }
public IEnumerable<SelectListItem> CategorySelectList { get; set; }
}
}
View
#model TestWebApplication.Models.ViewModels.ProductVM
#{
var title = "Create Product";
}
<form method="post" enctype="multipart/form-data">
#if(Model.Product.Id != 0)
{
title = "Edit Product";
<input asp-for="Product.Id" hidden />
}
<div class="border p-3">
<div class="form-group row">
<h2 class="text-info pl-3">#title</h2>
</div>
<br />
<div class="row">
<div class="col-8">
<div class="form-group row">
<div class="col-4">
<label asp-for="Product.Name"></label>
</div>
<div class="col-8">
<input asp-for="Product.Name" class="form-control"/>
<span asp-validation-for="Product.Name" class="text-danger"></span>
</div>
</div>
<br />
<div class="form-group row">
<div class="col-4">
<label asp-for="Product.Price"></label>
</div>
<div class="col-8">
<input asp-for="Product.Price" class="form-control"/>
<span asp-validation-for="Product.Price" class="text-danger"></span>
</div>
</div>
<br />
<div class="form-group row">
<div class="col-4">
<label asp-for="Product.Description"></label>
</div>
<div class="col-8">
<textarea asp-for="Product.Description" class="form-control summernote"> </textarea>
<span asp-validation-for="Product.Description" class="text-danger"></span>
</div>
</div>
<br />
<div class="form-group row">
<div class="col-4">
Image
</div>
<div class="col-8">
<input type = "file" name="files" id="uploadBox" multiple class="form-control"/>
</div>
</div>
<br />
<div class="form-group row">
<div class="col-4">
<label asp-for="Product.CategoryId"></label>
</div>
<div class="col-8">
<select asp-for="Product.CategoryId" asp-items="#Model.CategorySelectList" class="form-control">
<option disabled selected>---Select Category---</option>
</select>
<span asp-validation-for="Product.CategoryId" class="text-danger"></span>
</div>
</div>
<br />
<div class="form-group row">
<div class="col-8 offset-4 row">
<div class="col">
#if (Model.Product.Id != 0)
{
//update
<input type="submit" class="btn btn-info w-100" value="Update"/>
}
else
{
//create
<input type="submit" onclick="return validateInput()" class="btn btn-primary w-100" value="Create"/>
}
</div>
<div class="col">
<a asp-action="Index" class="btn btn-success w-100">
Back
</a>
</div>
</div>
</div>
</div>
<div class="col-4">
#* Keep this empty *#
</div>
</div>
</div>
</form>
#section Scripts
{
#{
<partial name= "_ValidationScriptsPartial.cshtml"/>
}
<script>
$(document).ready(function() {
$('.summernote').summernote(
{
height:250
});
});
function validateInput()
{
if (document.getElementById("uploadBox").value == "")
{
Swal.fire
(
'Error!',
'Please, upload an image',
'error'
)
return false;
}
return true;
}
</script>
}
Controller
using TestWebApplication.Data;
using TestWebApplication.Models;
using TestWebApplication.Models.ViewModels;
namespace TestWebApplication.Controllers
{
public class ProductController : Controller
{
private readonly ApplicationDbContext _db;
private readonly IWebHostEnvironment _webHostEnvironment;
public ProductController(ApplicationDbContext db, IWebHostEnvironment webHostEnvironment)
{
_db = db;
_webHostEnvironment = webHostEnvironment;
}
public IActionResult Index()
{
IEnumerable<Product> objList = _db.Product;
foreach (var item in objList)
{
item.Category = _db.Category.FirstOrDefault(category => category.Id == item.Id);
}
return View(objList);
}
// get - upsert
public IActionResult Upsert(int? id)
{
//IEnumerable<SelectListItem> CategoryDropDown = _db.Category.Select(i => new SelectListItem
//{
// Text = i.Name,
// Value = i.Id.ToString()
//});
//ViewBag.CategoryDropDown = CategoryDropDown;
//Product product = new Product();
ProductVM productVM = new ProductVM()
{
Product = new Product(),
CategorySelectList = _db.Category.Select(i => new SelectListItem
{
Text = i.Name,
Value = i.Id.ToString()
})
};
if(id == null)
{
// for create
return View(productVM);
}
else
{
productVM.Product = _db.Product.Find(id);
if (productVM.Product == null)
NotFound();
return View(productVM);
}
}
// post - upsert
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Upsert(ProductVM obj)
{
if (ModelState.IsValid)
{
var files = HttpContext.Request.Form.Files;
string webRootPath = _webHostEnvironment.WebRootPath;
if(obj.Product.Id == 0)
{
//Creating
string upload = webRootPath + WC.ImagePath;
string fileName = Guid.NewGuid().ToString();
string extention = Path.GetExtension(files[0].FileName);
using(var fileStream = new FileStream(Path.Combine(upload, fileName + extention), FileMode.Create))
{
files[0].CopyTo(fileStream);
}
obj.Product.Image = fileName + extention;
_db.Product.Add(obj.Product);
}
else
{
//Updating
}
return RedirectToAction("Index");
}
return View();
}
}
List of fields that participated in validation
From one answer, I realized that the Category field will remain null, and ef core will substitute the values. But I don't quite understand why so many fields are validated without being marked required in the model.
By receives a POST action, ModelState takes all of the name-value pairs and adds them as individual instances of ModelStateEntry to an instance of ModelStateDictionary.
ModelState checks all properties regardless of whether they have a Data annotations or not, such as you get a number, text, file etc. But for those data annotations you put on the properties the ModelState makes a special check based on it.
Just the properties of the model you passed to controller would be validated,you could try custom model validation follow this document:
https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-6.0#custom-attributes
And you could try with ModelState.AddModelError(string.Empty, "errormessage");add model level error in backend.

To send values of a checkbox list class to the server using AJAX in ASP.Net Core

I have the following model code for the checkbox list.
public class ReportViewModel
{
public List<Guid> Reports { get; set; }
public SelectList ReportList { get; set; }
public List<CheckBoxResponse> Status { get; set; }
}
public class CheckBoxResponse
{
public string ItemText { get; set; }
public bool Selected { get; set; }
}
This is my view :
<form id="frmReport">
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label asp-for="Reports"></label><br />
<select asp-for="Reports" asp-items="Model.ReportList" class="form-control" multiple></select>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<label>Status</label> <br />
#for (var i = 0; i < Model.Status.Count; i++)
{
<input type="checkbox" asp-for="#Model.Status [i].Selected" />
<label asp-for="#Model.Status[i].Selected"> #Model.Status[i].ItemText</label>
<input type="hidden" asp-for="#Model.Status[i].ItemText" />
}
</div>
</div>
<div class="row">
<div class="col-xs-12" style="padding-top: 10px; padding-bottom: 10px;">
<a id="submit" class="btn btn-primary" title="Submit">Submit</a>
</div>
</div>
</form>
There are 3 values in the check box list, and so there are 3 check boxes. I now need to pass the values to the server on click of button using jquery. This is my code :
$(document).on('click', '#submit', function (e) {
var reports = $("#Reports").find("option:selected").val();
//Need to add checkbox class to submit to the server
var model = {
Reports : reports,
Status : ??
}
}
I need to send the checkbox list to the server by adding it to the model. How do I do it?
You can put the checkboxes on a form (not nested, just use one form if it's okay) and then serialize the form and submit the data.
Do you want to send the value to the server? Then you should add value to input, and create an
array to store the selected value and then pass them, check this:
#for (var i = 0; i < Model.Status.Count; i++)
{
<input type="checkbox" asp-for="#Model.Status[i].Selected" value="#Model.Status[i].ItemText"/>
<label asp-for="#Model.Status[i].Selected">#Model.Status[i].ItemText</label>
<input type="hidden" asp-for="#Model.Status[i].ItemText" />
}
Jquery:
$(document).ready(function () {
$('#submit').click(function () {
var selected = []; //array to store
$('input:checked').each(function () {
selected.push($(this).attr("value")); //push value to array
});
$.ajax({
type: "POST",
url: '#Url.Action("Test", "Home")',
data: { Selecteditem: selected } //pass as string
});
});
});
The server:
public IActionResult Test(List<string> Selecteditem)
Result:

How can I set model input for an object attribute that exist in layers of list with asp tag-helper?

I have a model that consists of many layers. On the main frame, there will be an object for basic input and a list of object that contains a model to store view data but inside it, each item will have a data field to store its new value which I will also consider as input data. My problem is I don't know how to call, set that data field inside tag helper since it's cover by list of list. What I want to achieve is to pass all data back to controller.
public class TenDongThuocCongTy
{
public int Id { get; set; }
public int CauHinhBangId { get; set; }
public string CongThucDong { get; set; }
public string TenDong { get; set; }
public int CauHinhBang_Cha { get; set; }
[NotMapped]
public string inputValue { get; set; }
}
public class LayThongTinBangThuocCongTyThanhVien
{
public int Cttv_ThuocBangId { get; set; }
public int CauHinhBangID { get; set; }
public int CttvId { get; set; }
public string TenDong { get; set; }
public string CongThucDong { get; set; }
public string DichCongThuc { get; set; }
public List<TenDongThuocCongTy> TenDongThuocCongTies { get; set; }
}
public class MuaVuTruocUpsertModel
{
[DisplayName("Day")]
public DateTime? Ngay { get; set; }
[Required(ErrorMessage = "Number")]
[DisplayName("Number")]
public int? STT { get; set; }
}
public class TongHopItemMuaVuTruoc
{
public List<LayThongTinBangThuocCongTyThanhVien> MenuItemMuaVutruoc { get; set; }
public MuaVuTruocUpsertModel muaVuTruocModel {get; set;}
}
As in the model above, I want to access to the defined meaning of 'inputValue' then put it in:
#model MFF.Infrastructure.Models.TongHopItemMuaVuTruoc
<input asp-for="inputModel" type="text"/>
What I want to achieve is to pass all data back to controller.
To pass data from view to the controller, you could use the following methods:
Use asp.net core Model Binding and Submit button to submit the form.
Use JQuery Ajax submits the form data or a JavaScript object to the controller.
Please refer the following sample code:
Controller:
public IActionResult Index2()
{
TongHopItemMuaVuTruoc tongHopItemMuaVuTruoc = new TongHopItemMuaVuTruoc()
{
MenuItemMuaVutruoc = new List<LayThongTinBangThuocCongTyThanhVien>()
{
new LayThongTinBangThuocCongTyThanhVien()
{
TenDongThuocCongTies = new List<TenDongThuocCongTy>()
{
new TenDongThuocCongTy()
{
TenDong = "TD 1",
inputValue = "AA",
},
new TenDongThuocCongTy()
{
TenDong = "TD 2",
inputValue = "BB",
}
}
}
}
};
return View(tongHopItemMuaVuTruoc);
}
[HttpPost]
public IActionResult Index2(TongHopItemMuaVuTruoc tongHopItemMuaVuTruoc)
{
if (ModelState.IsValid)
{
//do something
}
return View(tongHopItemMuaVuTruoc);
}
Index2 View page (Index2.cshtml): Here I add two buttons, the "Submit" button will submit the form using the first method, the "Ajax Submit" button will submit the form using JQuery Ajax method. And you can add other properties using the similar tag.
#model WebApplication6.Models.TongHopItemMuaVuTruoc
<div class="row">
<div class="col-md-4">
<form id="mainform" asp-action="Index2">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="muaVuTruocModel.Ngay" class="control-label"></label>
<input asp-for="muaVuTruocModel.Ngay" class="form-control" />
<span asp-validation-for="muaVuTruocModel.Ngay" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="muaVuTruocModel.STT" class="control-label"></label>
<input asp-for="muaVuTruocModel.STT" class="form-control" />
<span asp-validation-for="muaVuTruocModel.STT" class="text-danger"></span>
</div>
#for (var i = 0; i < Model.MenuItemMuaVutruoc.Count(); i++)
{
for (var j = 0; j < Model.MenuItemMuaVutruoc[i].TenDongThuocCongTies.Count; j++)
{
<div class="form-group">
<input asp-for="MenuItemMuaVutruoc[i].TenDongThuocCongTies[j].TenDong" type="text" />
</div>
<div class="form-group">
<input asp-for="MenuItemMuaVutruoc[i].TenDongThuocCongTies[j].inputValue" type="text" />
</div>
}
}
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" /> <input type="button" id="btnSubmit" value="Ajax Submit" class="btn btn-primary" />
</div>
</form>
</div>
</div>
At the end of the above view page, add the following scripts:
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
$(function () {
$("#btnSubmit").click(function () {
$.ajax({
url: "Test/Index2",
method: "Post",
data: $("#mainform").serialize(),
success: function () {
alert("sueess");
},
error: function (error) {
alert("error");
}
});
});
})
</script>
}
The output like this:
Reference:
Razor syntax reference for ASP.NET Core
I finally figure it out. What I have to do is treated my model as an array object. The code below returns all of my data, including default data and newly input ones, back to Controller successfully.
#for (int i = 0; i < Model.MenuItemMuaVutruoc.Count; i++)
{
//Value for Model
<input type="hidden" asp-for="MenuItemMuaVutruoc[i].CttvId" />
<input type="hidden" asp-for="MenuItemMuaVutruoc[i].Cttv_ThuocBangId" />
<input type="hidden" asp-for="MenuItemMuaVutruoc[i].CauHinhBangID" />
<input type="hidden" asp-for="MenuItemMuaVutruoc[i].TenDong" />
<input type="hidden" asp-for="MenuItemMuaVutruoc[i].CongThucDong" />
<input type="hidden" asp-for="MenuItemMuaVutruoc[i].DichCongThuc" />
#for (int j = 0; j < danhmuc.TenDongThuocCongTies.Count; j++)
{
//Value cho tung item
<input type="hidden" asp-for="MenuItemMuaVutruoc[i].TenDongThuocCongTies[j].Id" />
<input type="hidden" asp-for="MenuItemMuaVutruoc[i].TenDongThuocCongTies[j].CauHinhBangId" />
<input type="hidden" asp-for="MenuItemMuaVutruoc[i].TenDongThuocCongTies[j].CongThucDong" />
<input type="hidden" asp-for="MenuItemMuaVutruoc[i].TenDongThuocCongTies[j].CauHinhBang_Cha" />
<input type="hidden" asp-for="MenuItemMuaVutruoc[i].TenDongThuocCongTies[j].TenDong" />
var item = danhmuc.TenDongThuocCongTies.ElementAt(j);
<h6 class="col-md-4 col-lg-4 col-sm-4 mt-lg-2 mt-md-2 mt-2 mt-sm-2">
#item.TenDong
</h6>
<input asp-for="MenuItemMuaVutruoc[i].TenDongThuocCongTies[j].inputValue" type="text" class="form-control col-md-8 col-lg-8 col-sm-8 mt-lg-2 mt-md-2 mt-2 mt-sm-2" />
}
}

Razor Page Partial renders Input and hidden Input

I´m experiencing a very strange behaviour with ASP .net core 2.2 Razor Pages.
Let´s say I have a standard Razor Page. The User can send a request over that page for a new Team that should be provisioned. I have some fields like, DisplayName etc. which the user can edit freely and a dropdown to choose from where he can select from which existing Team he would like to clone some settings from. After the User selected it, I´m using Ajax to render the partial View on the right side of the view and the User can also select some additional options. Until here I´m fine and everything is working so far. I expected, if the user clicks the save / submit button that everything will be included in the post request, even the partial View Data. After digging around and troubleshooting I found out that I have to set ViewData.TemplateInfo.HtmlFieldPrefix to name everything like in the Parent View to not mess the Binding up. Works also.
The strange behaviour is, that after the Partial View was rendered, in HTML two Inputs fields were generated. One where the user can select and one which is hidden. I´ll show my code and also the rendered HTML File so that guys can make yourself a picture of that. What now happens is, the hidden fields have a default or null values and these are going to be included in the request. I have no idea where they come from and / or how to fix it or what I did wrong?
I will shorten my code a little bit but I will include the necessary parts.
Team Request Model
public class TeamRequestModel
{
public string DisplayName { get; set; }
public string Description { get; set; }
public string Visibility { get; set; }
public List<string> Owners { get; set; }
public string CloneTeamID { get; set; }
public TeamCloneSettings TeamCloneSettings { get; set; }
public TeamRequestModel()
{
TeamCloneSettings = new TeamCloneSettings();
}
}
Team Clone Settings (only Parts can be Set by the user
public class TeamCloneSettings
{
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
public string PartitionKey;
public string DisplayName { get; set; }
public bool Released { get; set; }
public bool FixedVisibility { get; set; }
public string Visibility { get; set; }
public bool CloneEverything { get; set; }
public TeamCloneParts Parts { get; set; }
public TeamCloneSettings()
{
Parts = new TeamCloneParts();
}
}
public class TeamCloneParts
{
public bool CloneApps { get; set; }
public bool CloneChannels { get; set; }
public bool CloneTabs { get; set; }
public bool CloneSettings { get; set; }
}
}
Main "Team Request View"
#page
#model iwDashboard.Pages.Teams.TeamRequest
#{
ViewData["Title"] = Model.Title;
}
#{
ViewBag.PageTitle = Model.Title;
}
<style>
textarea {
resize: none;
}
</style>
<section class="content">
<form method="post" asp-page-handler="SaveTeamRequest" class="col-md-12">
<div class="row">
<div class="col-md-3">
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">Team Details</h3>
</div>
<div class="card-body">
<div class="form-group">
<label for="displayName">Display Name</label>
<input id="displayName" asp-for="#Model.teamRequest.DisplayName" type="text" class="form-control" required />
</div>
... More fields
<div style="float: left; width: 40%">
<button type="button" onclick="history.go(-1)" data-toggle="tooltip" title="Back" class="btn btn-primary btn-block btn-sm"><i class="fa fa-arrow-circle-left"></i><b> Back</b></button>
</div>
<div style="float: right; width: 40%">
<button type="submit" data-toggle="tooltip" title="Save" class="btn btn-success btn-block btn-sm"><i class="fas fa-save"></i><b> Save</b></button>
</div>
</div>
<!-- /.card-body -->
</div>
<!-- /.card -->
</div>
<div class="col-md-6">
<div class="card card-secondary">
<div class="card-header">
<h3 class="card-title">Team Settings</h3>
</div>
<div class="card-body">
<!--partial comes here-->
<div id="partialDiv"></div>
</div>
<!-- /.card-body -->
</div>
<!-- /.card -->
</div>
</div>
</form>
</section>
#section Scripts
{
<script>
function GetTeamTemplateProperties() {
var selectedTeam = $('#teamTemplateSelection').val();
$.ajax({
type: "Get",
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
url: '/Teams/TeamRequest?handler=TeamTemplateProperties',
data: {
SelectedTeam: selectedTeam
},
success: function (result) {
$("#partialDiv").after(result);
}
})
};
</script>
}
Get Template Properties Post called by Ajax
public async Task<IActionResult> OnGetTeamTemplateProperties(string SelectedTeam)
{
TeamCloneSettings teamCloneSettings = new TeamCloneSettings();
teamRequest = new TeamRequestModel();
if (!string.IsNullOrEmpty(SelectedTeam))
{
teamCloneSettings = await _teamCloneSettingService.GetTeamCloneSettingByIdAsync(SelectedTeam);
teamRequest.TeamCloneSettings = teamCloneSettings;
}
ViewData.TemplateInfo.HtmlFieldPrefix = "teamRequest";
SelectedValue = SelectedTeam;
return new PartialViewResult
{
ViewName = "_TeamCloneSettingsPartial",
ViewData = new ViewDataDictionary<TeamRequestModel>(ViewData, teamRequest)
};
}
View Model BindProperty
...More Code
[BindProperty]
public TeamRequestModel teamRequest { get; set; }
[BindProperty]
public string SelectedValue { get; set; }
...More Code
_TeamCloneSettingsPartial
#model iwDashboard.Models.TeamRequestModel
#{
<!--
Check if fixed visibility is enabled and
disable selection of visibility if it is
-->
string disabled = null;
string options = null;
if (Model.TeamCloneSettings.FixedVisibility)
{
disabled = "disabled";
options = Model.Visibility;
}
}
<div class="form-group">
<input type="checkbox" hidden id="cloneEverthing" checked=#Model.TeamCloneSettings.CloneEverything>
<ul class="list-group list-group-unbordered mb-3">
<li class="list-group-item">
<label for="visibility">Visibility</label>
<select class="form-control #disabled custom-select" asp-for="TeamCloneSettings.Visibility" required>
#if (!string.IsNullOrEmpty(disabled))
{
<option readonly selected>#Model.TeamCloneSettings.Visibility</option>
}
else
{
<option>Public</option>
<option>Private</option>
}
</select>
</li>
<!-- Checkbox parts here
Javascript will check if "CloneEverything"
is enabled and will disable all of the following checkboxes
-->
<li class="list-group-item">
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="cloneApps" checked=#Model.TeamCloneSettings.Parts.CloneApps asp-for="TeamCloneSettings.Parts.CloneApps">
<label class="custom-control-label" for="cloneApps">Clone Apps</label>
</div>
</div>
</li>
<li class="list-group-item">
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="cloneChannels" checked=#Model.TeamCloneSettings.Parts.CloneChannels asp-for="TeamCloneSettings.Parts.CloneChannels">
<label class="custom-control-label" for="cloneChannels">Clone Channels</label>
</div>
</div>
</li>
<li class="list-group-item">
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="cloneSettings" checked=#Model.TeamCloneSettings.Parts.CloneSettings asp-for="TeamCloneSettings.Parts.CloneSettings">
<label class="custom-control-label" for="cloneSettings">Clone Settings</label>
</div>
</div>
</li>
<li class="list-group-item">
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="cloneTabs" checked=#Model.TeamCloneSettings.Parts.CloneTabs asp-for="TeamCloneSettings.Parts.CloneTabs">
<label class="custom-control-label" for="cloneTabs">Clone Tabs</label>
</div>
</div>
</li>
</ul>
</div>
Strange rendered Input field
https://i.stack.imgur.com/aZtUD.png
As you can see, the Input is rendered twice and only the hidden values will be transmitted. But this only happens for the Input fields in the Partial View, all other fields are fine.
Any Ideas? Would be great :-).
Thanks a lot!!
Having 2 input fields generated is normal when using the asp-for tag helper on a checkbox. It will create the checkbox itself but also a hidden input field for the model binder to send the value chosen by the user.
Only the hidden field generated by the tag helper will be used to send the data.
Found a solution here:
asp.net mvc: why is Html.CheckBox generating an additional hidden input
Might not be the best one but it works for me:
checking with Javascript if the Checkbox is selected an then setting the value of the hidden field:
if ($('[name="foo"]:checked').length > 0)
$('[name="foo"]:hidden').val(true);
Thanks everybody!

Categories

Resources