Populate fields based on other fields ASP.NET Razor Pages - javascript

I know that this question might have been already on this site, but there are some different things in my approach because I use #Html.EditFor and #Html.DropDownList.
So I have a drop down list and when I choose the ID there I want to retrieve some information from the DB then populate some fields in the current form. I know that I should use JS but I don't know how.
View:
#model TestApp.Dtos.InsertDto
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="col-md-9">
#Html.DropDownListFor(model => model.Category, new SelectList(Model.ListOfCategory, "Text", "Text"), "-- Please select --", htmlAttributes: new { #class = "form-control"});
</div>
<div class="col-md-9">
#Html.EditFor(model => model.Car, new{htmlAttributes = new { #class = "form-control" }});
</div>
#*And then the form continues with other fields and after that the submit button *#
}

You can use ajax to get data from backend,and put the result data into somewhere you want.Here is a simple demo to get a selectListItem from backend and put it into a div.If you want to do something more complex,you need to share the structure of InsertDto,and explain clearly what kind of data you will get from db and explain what does populate some fields in the current form mean?
View:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="col-md-9">
#Html.DropDownListFor(model => model.Category, new SelectList(Model.ListOfCategory, "Text", "Text"), "-- Please select --", htmlAttributes: new { #class = "form-control" ,#onchange = "getData()" })
</div>
<div id="dbdata">
</div>
}
js:
<script>
function getData() {
$.ajax({
type: "POST",
data: { Category: $("#Category").val() },
url: '/B/GetData',
}).done(function (result) {
$("#dbdata").html("the selected value is " + result.text);
});
}
</script>
Model:
public class InsertDto
{
public string Category { get; set; }
public List<SelectListItem> ListOfCategory { get; set; }
}
controller:
public IActionResult Index(string id)
{
InsertDto i = new InsertDto { ListOfCategory = new List<SelectListItem> { new SelectListItem { Text = "t1" }, new SelectListItem { Text = "t2" }, new SelectListItem { Text = "t3" } } };
return View(i);
}
public SelectListItem GetData(string Category)
{
return new SelectListItem { Text = Category, Value = Category + "value" };
}
result:

Related

Why is this Javascript Error occurring in MVC Web application?

Okay I'm totally new to this so I'm not going to get a lot of the terminology right, but it's an ASP.NET MVC application where a create view is supposed to have an autocomplete function on the "StudentID" text box. It doesn't work. On the console window I get an error message "Autocomplete is not a function". This is strange because the intellisense at the beginning does give me autocomplete. I don't know what I'm supposed to paste below but I put in the javascript as well as the applicable Controller code. LMK if there's anything else you need to see. Thanks in advance.
P.S. If you know a better way to do autocomplete (this is done through a class that we got the code from some website and looks more complicated than similar things I did in the past) please let me know that too.
<script>
$("#Student_FirstName").autocomplete(
{
source: function (request, response)
{
$.ajax(
{
url: "/Enrollments/GetStudents",
dataType: "json",
type: "POST",
data:
{
term: request.searchTerm
},
success: function (data) {
console.log(data);
response($.map(data, function (item) {
return {
label: item.Name, value: item.Name, id: item.id
};
}))
}
});
},
minLength: 2,
select: function (event, query)
{
console.log(query);
$("#StudentID").val(query.item.id);
}
});
</script>
And now from later on in the Create view:
<div class="form-group">
#Html.LabelFor(model => model.StudentID, "StudentID", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Student.FirstName, new { htmlAttributes = new {#class = "form-control"}})
#Html.HiddenFor(model => model.StudentID)
#Html.ValidationMessageFor(model => model.StudentID, "", new { #class = "text-danger" })
</div>
</div>
And finally from the Controller Class:
// GET: Enrollments/Create
public ActionResult Create()
{
ViewBag.CourseID = new SelectList(db.Courses, "CourseID", "Title");
ViewBag.StudentID = new SelectList(db.Students, "StudentID", "LastName");
ViewBag.InstructorID = new SelectList(db.Instructors, "ID", "FirstName");
return View();
}
// POST: Enrollments/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "EnrollmentID,Grade,CourseID,StudentID,InstructorID")] Enrollment enrollment)
{
if (ModelState.IsValid)
{
db.Enrollments.Add(enrollment);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CourseID = new SelectList(db.Courses, "CourseID", "Title", enrollment.CourseID);
ViewBag.StudentID = new SelectList(db.Students, "StudentID", "LastName", enrollment.StudentID);
ViewBag.InstructorID = new SelectList(db.Instructors, "ID", "FirstName", enrollment.InstructorID);
return View(enrollment);
}

Using Typeahead.js for dropdown list replacement MVC

I currently use MVC dropdown list for displaying my dropdown lists. I am looking to move my entire page to JS and web api's. The current code functions and works fine with my controller. I have some sample code that works for main table on this API but Looking to see if I can get it to function the same way I use the MVC dropdown plugins but with TypeAhead.js
Current Code for StanceType DropDownList:
<div class="row">
<div class="col-sm-4 form-group">
#Html.LabelFor(m => m.Stances.Name) #Html.TextBoxFor(m => m.Stances.Name, new { #class = "form-control col-lg" })
</div>
<div class="col-sm-4 form-group">
#Html.LabelFor(m => m.Stances.StancesTypesId) #Html.DropDownListFor(m => m.Stances.StancesTypesId, new SelectList(Model.StancesTypes, "Id", "Name"), "Select Stance Type", new { #class = "form-control col-lg" })
</div>
<div class="col-sm-4 form-group">
#Html.LabelFor(m => m.Stances.BrandsId) #Html.DropDownListFor(m => m.Stances.BrandsId, new SelectList(Model.Brands, "Id", "Name"), "Select Brand", new { #class = "form-control col-lg" })
</div>
</div>
Current Controller:
public ActionResult Details() {
var stancesTypes = _context.StancesTypes.ToList();
var priority = _context.Priority.ToList();
var brands = _context.Brands.ToList();
var viewModel = new StancesViewModel {
StancesTypes = stancesTypes,
Priority = priority,
Brands = brands
};
return View("Details", viewModel);
}
This is new typeAhead.js and API Controller that I am trying but it just displays the Name data from the Stances database and not the Name field for StanceTypes field.
var stances = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('StancesTypesId'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: '/api/stances?query=%QUERY',
wildcard: '%QUERY'
}
});
$('#stancetype').typeahead({
minLength: 0,
hightlight: true
}, {
name: 'StancesTypesId',
display: 'name',
source: stances
});
// GET /api/Stances
public IEnumerable <StancesDto> GetStances() {
//get accountid from user
string userId = User.Identity.GetUserId();
var userAccountID = _context.AccountProfile.Single(c => c.UserId == userId);
var stancesTypes = _context.StancesTypes.ToList();
var priority = _context.Priority.ToList();
var brands = _context.Brands.ToList();
var viewModel = new StancesViewModel {
StancesTypes = stancesTypes,
Priority = priority,
Brands = brands
};
return _context.Stances.ToList().Select(Mapper.Map <Stances, StancesDto> ).Where(c => c.AccountGUID == userAccountID.AccountGUID);
}

iTextSharp .Net Action Result to download as a pdf through ajax

I am using iTextSharp to convert a razor view to a pdf that can be downloaded by way of a C# controller. This current implementation works perfectly, however I would like to pass a model from a view to the pdf controller and have the action result download within the browser
Here is my current controller:
public ActionResult Report(MyModel model)
{
// The below method is a custom implementation using iTextSharp
return new FoilPdfActionResult(model, (writer, document) =>
{
document.SetPageSize(PageSize.LETTER.Rotate());
document.NewPage();
})
{
FileDownloadName = "testing.pdf",
};
}
Here is my AJAX call:
function sendForm(model) {
$.ajax({
type: 'POST',
url: '#Url.Action("Report")',
data: model,
success: function (data) {
console.log(data);
},
error: function (xhr, textStatus, errorThrown) {
}
});
}
If I just visit the path of the controller directly at "/Report" it downloads the file correctly within the browser.
If I use the ajax call above to call the controller, it passes the model correctly and returns the pdf result through the data variable on success but does not actually download the pdf. Is is possible to have the pdf downloaded instead of being passed through the data variable?
Recently has a (2) similar situation and found that there are no real baked in ways to do it via ajax. GOOD NEWS: It's actually really easy to do and you do not need an ajax call.
What you can do is submit a form post request and in your controller post action you can generate the file in memory and use "return File()" to pump the file back to the view without the view reloading.
Here is an example using iTextSharp:
Example Model:
public class TestM
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Number { get; set; }
}
View (basic auto generated create)
#model DeleteMeWeb45.Models.TestM
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>TestM</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.LastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Number, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Number, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Number, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
Controller:
public ActionResult Index()
{
TestM t = new TestM();
return View(t);
}
[HttpPost]
public ActionResult Index(TestM t)
{
if(ModelState.IsValid)
{
Document doc = new Document(iTextSharp.text.PageSize.LETTER, 10, 10, 42, 30);
byte[] pdfBytes;
BaseFont bfTimes = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, false);
Font timesBold = new Font(bfTimes, 12, Font.BOLD);
using (var mem = new MemoryStream())
{
PdfWriter wri = PdfWriter.GetInstance(doc, mem);
doc.SetMargins(20, 20, 20, 60);
doc.Open();
var orderInfoTable = new PdfPTable(2);
orderInfoTable.AddCell(new Phrase("First Name:", timesBold));
orderInfoTable.AddCell(new Phrase(t.FirstName, timesBold));
orderInfoTable.AddCell(new Phrase("Last Name:", timesBold));
orderInfoTable.AddCell(new Phrase(t.LastName, timesBold));
orderInfoTable.AddCell(new Phrase("Number:", timesBold));
orderInfoTable.AddCell(new Phrase(t.Number.ToString(), timesBold));
doc.Add(orderInfoTable);
doc.Close();
pdfBytes = mem.ToArray();
}
return File(pdfBytes, "application/pdf", "Weeeeeee_" + DateTime.Now.ToString("_MM-dd-yyyy-mm-ss-tt") + ".pdf");
}
else
{
return View(t);
}
}
In the event that you want to keep your form submit button as is (so it saves or does whatever) and want an extra button that just downloads then you would modify the above example as such:
View:
Change 1. Give the form an ID:
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "transferForm" }))
Change 2. Add a button and JS to submit the form at an alternative location:
<div class="row">
<div class="btn btn-primaryDark btn-sm" id="btnRunReport" style="min-width:120px;">Run Report</div>
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script>
$(document).ready(function () {
$("#btnRunReport").click(function () {
$('#transferForm').attr('action', "/Home/JSFUN").submit();
});
});
</script>
}
Controller Changes:
1. Create a new controller action to handle the post request:
[HttpPost]
public ActionResult JSFUN(TestM t)
{
Document doc = new Document(iTextSharp.text.PageSize.LETTER, 10, 10, 42, 30);
byte[] pdfBytes;
BaseFont bfTimes = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, false);
Font timesBold = new Font(bfTimes, 12, Font.BOLD);
using (var mem = new MemoryStream())
{
PdfWriter wri = PdfWriter.GetInstance(doc, mem);
doc.SetMargins(20, 20, 20, 60);
doc.Open();
var orderInfoTable = new PdfPTable(2);
orderInfoTable.AddCell(new Phrase("First Name:", timesBold));
orderInfoTable.AddCell(new Phrase(t.FirstName, timesBold));
orderInfoTable.AddCell(new Phrase("Last Name:", timesBold));
orderInfoTable.AddCell(new Phrase(t.LastName, timesBold));
orderInfoTable.AddCell(new Phrase("Number:", timesBold));
orderInfoTable.AddCell(new Phrase(t.Number.ToString(), timesBold));
doc.Add(orderInfoTable);
doc.Close();
pdfBytes = mem.ToArray();
}
return File(pdfBytes, "application/pdf", "Weeeeeee_" + DateTime.Now.ToString("_MM-dd-yyyy-mm-ss-tt") + ".pdf");
}
This way your user can use the form submit button and a export button for different purposes.
You can create a Iframe element on page and make it hidden and then bind "src" property with complete path of action, it will download your pdf for sure. I have done this many time. You can take help from this link https://www.codeproject.com/Questions/470316/how-to-download-attachment-using-Iframe

How to pass data from a form to my controller, and then back to my client-side javascript?

I have a form in my webpage that asks for first and last name. When the user submits this form I would like the data to be passed to a function in my controller, where it is used to find the corresponding user in our Active Directory. I want to then return the matching Email address to a Javascript function, when then displays that information on my page. Is this the "correct" way to go about doing this, and if yes, how would I structure a function in my controller to accept form input, and return data to my client side javascript?
What I have so far in my controller:
public SearchResult[] searchAD(String fname, String lname)
{
Func<System.DirectoryServices.ActiveDirectory.Domain> domain = System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain;
System.DirectoryServices.DirectoryEntry root = new DirectoryEntry("LDAP://"+domain);
DirectorySearcher searcher = new DirectorySearcher();
searcher.SearchRoot = root;
searcher.SearchScope = SearchScope.Subtree;
searcher.Filter = string.Format("(&(objectCategory=person)(objectClass=user)(givenName={0})(sn={1}))", fname, lname);
SearchResult[] results = new SearchResult['a'];
searcher.FindAll().CopyTo(results, 0);
return results;
}
And my form:
#using (Html.BeginForm("searchAD", "AD", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.firstName, "First Name", htmlAttributes: new { #class = "control-label" })
<div>
#Html.EditorFor(model => model.firstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.firstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.lastName, "Last Name", htmlAttributes: new { #class = "control-label" })
<div>
#Html.EditorFor(model => model.lastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.lastName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div>
<input type="submit" value="Search" class="btn" />
</div>
</div>
}
You can Store value in TempData and get it on view
public ActionResult searchAD(String fname, String lname)
{
Func<System.DirectoryServices.ActiveDirectory.Domain> domain = System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain;
System.DirectoryServices.DirectoryEntry root = new DirectoryEntry("LDAP://"+domain);
DirectorySearcher searcher = new DirectorySearcher();
searcher.SearchRoot = root;
searcher.SearchScope = SearchScope.Subtree;
searcher.Filter = string.Format("(&(objectCategory=person)(objectClass=user)(givenName={0})(sn={1}))", fname, lname);
SearchResult[] results = new SearchResult['a'];
searcher.FindAll().CopyTo(results, 0);
TempData["Result"]=results;
return View("ViewName");
}
In View (Jquery)
$(function(){
if ('#TempData["Result"]' != '')
{
// call your function here and pass TempData Value
}
});
Above is not perfect solution for your posted issue because tempdata or viewbag are not meant for that.If you need to post data again back from control to view then its always make use of #Ajax.BeginForm
#using (Ajax.BeginForm("ActionName", "Controller", new AjaxOptions { OnComplete = "Sucess" }))
in jquery you have to write Success function like below :
function Sucess(arg) {
//arg.data
}
in arg.data you will get that object what you are passing from controller.More ever #Html.BeginForm refreshing your whole page not specific content but with With Ajax.begin form you can manage to reload only those content which is under ajax.begin form.

Validation in Partial view inside popup

I'm working in MVC and i have one scenario as follows:
I have a view called ManageResource where i il show the available resource's in grid and a button to add new resource. if i click on the add new resource button a popup il open with the partialview inside it, i have to display the validation result in popup itself when i click save with out entering any values and when i enter the required fields the values should be populated in the grid and the popup should be closed.`
"iam not getting validation result in popup, but can able to save data's"
following is my code:
Model-tblUser
public partial class tblUser
{
public int UID { get; set; }
[Required]
public int EmpID { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public decimal Salary { get; set; }
}
View-ManageResource
function Create() {
BootstrapDialog.show({
title: "Add Resource",
message: $('<div id="CreatePopup"></div>').load('#Url.Action("Create", "Resource")')
});
return false;
}
<input type="button" id="AddNewCompany" onclick="Create()" class="push_button blue btn_width" value="Add New Resource" />
partial view- Create
function SaveResource() {
var obj = [];
var EmpID = $('#EmpID').val();
var FirstName = $('#FirstName').val();
var LastName = $('#LastName').val();
var Salary = $('#Salary').val();
if ($("#IsActive").attr('checked', true)) {
var IsActive = 1;
}
else {
var IsActive = 0
}
var newrecord = {
"EmpID": EmpID, "FirstName": FirstName, "LastName": LastName, "Salary": Salary,
};
var senddata = JSON.stringify(newrecord);
jQuery.ajax({
type: "POST",
url: '#Url.Action("Create", "Resource")',
data: JSON.stringify({ "data": senddata }),
datatype: 'json',
contentType: "application/json; charset=utf-8",
success: function (result) {
if (result == true) {
window.location.href = '#Url.Action("ManageResource", "Resource")';
} else {
$("#CreatePopup").html(result);
}
}
});
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(false)
<div class="form-group">
#Html.LabelFor(model => model.EmpID, "Employee ID", new { #class = "control-label col-md-1 col-md-3" })
<div class="col-md-6">
#Html.EditorFor(model => model.EmpID)
#Html.ValidationMessageFor(model => model.EmpID)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FirstName,"First Name", new { #class = "control-label col-md-1 col-md-3" })
<div class="col-md-6">
#Html.EditorFor(model => model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastName,"Last Name", new { #class = "control-label col-md-1 col-md-3" })
<div class="col-md-6">
#Html.EditorFor(model => model.LastName)
#Html.ValidationMessageFor(model => model.LastName)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-5 col-md-10">
<input type="button" id="CreateResource" onclick="SaveResource()" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
Resource Controller
public PartialViewResult Create(string data)
{
JObject o = JObject.Parse(data);//parsing the json data
tblUser tbluser = new tblUser(); //creating instance for model tblUser
if ((string)o["EmpID"] != "" && (string)o["FirstName"] != "")// if all the required fields are present then add to db
{
db.tblUsers.Add(tbluser);//assign values here
tbluser.EmpID = (int)o["EmpID"];
tbluser.FirstName = (string)o["FirstName"];
tbluser.FirstName = (string)o["FirstName"];
tbluser.LastName = (string)o["LastName"];
tbluser.EmailID = (string)o["EmailID"];
tbluser.Password = (string)o["Password"];
tbluser.RoleID = (int)o["RoleID"];
tbluser.DeptID = (int)o["DeptID"];
tbluser.DesignationID = (int)o["DesignationID"];
tbluser.Salary = (int)o["Salary"];
tbluser.IsActive = (bool)o["IsActive"];
tbluser.CreatedBy = 121;
tbluser.CreatedDate = System.DateTime.Now;
tbluser.UpdatedBy = 121;
tbluser.UpdatedDate = System.DateTime.Now;
db.SaveChanges();
return RedirectToAction("ManageResource");//return to main view when saved
}
else
{
//return with validation summary to partialview popup
return PartialView(tbluser);
}
}
When you load a form using AJAX you need to tell jQuery unobtrusive validation to add the validation data- properties to the form elements. You need to add: $.validator.unobtrusive.parse('#YourFormSelector');
after the .load is completed.
function Create() {
BootstrapDialog.show({
title: "Add Resource",
message: $('<div id="CreatePopup"></div>').load('#Url.Action("Create","Resource")'
, function() {$.validator.unobtrusive.parse('#YourFormSelector');})
});
return false;
}

Categories