MVC3 razor How to repeatedly add Set of fields to my page on clicking a button? - asp.net-mvc-3

How to repeatedly add Set of fields to my page on clicking a button?
I have a button "Add records" on my ParentView.cshtml
on Click of this "Add records" button ,I need the below mentioned razor view(childView.cshtml) to be appended on my ParentView.Each time I click of this "Add records" button ,I need new empty ChildView.cshtml to be appended to my Parent view.Can some one help me how can I achieve this functionality ?
ChildView.cshtml
<p>Record index
#Html.EditorFor(model => model.Name)
#Html.EditorFor(model => model.Address)
#Html.EditorFor(model => model.Location)
<input type="submit" id="btnSave" value="Save" />
My ParentView.cshtml will look like below
#model MyWebRole.ViewModels.MyViewModel
#{
ViewBag.Title = "Address Book";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm())
{
<fieldset>
<legend style="font-size: small;">Add Address records </legend>
<br />
<table>
<tr>
<td rowspan="5">
<img alt="" id="imageBox" src="" width="395" height="225" />
</td>
<td>
<span>Address Book </span>
<br />
</td>
<td>
#Html.EditorFor(model => model.REcordTitle)
#Html.ValidationMessageFor(model => model.REcordTitle)
</td>
</tr>
------------------------
------------------------
</table>
<div><input type="submit" id="btnAdd records" value="Add Records" /></div>
</fieldset>
}

You could use the built-in Ajax helpers?
#model MyWebRole.ViewModels.MyViewModel
#{
ViewBag.Title = "Address Book";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Ajax.BeginForm(new AjaxOptions() {
UpdateTargetId = "RecordSection",
InsertionMode = InsertionMode.InsertAfter,
}))
{
<fieldset>
<legend style="font-size: small;">Add Address records </legend>
<br />
<table>
<tr>
<td rowspan="5">
<img alt="" id="imageBox" src="" width="395" height="225" />
</td>
<td>
<span>Address Book </span>
<br />
</td>
<td>
#Html.EditorFor(model => model.REcordTitle)
#Html.ValidationMessageFor(model => model.REcordTitle)
</td>
</tr>
------------------------
------------------------
</table>
<div><input type="submit" id="btnAdd records" value="Add Records" /></div>
</fieldset>
}
<div id="RecordSection">
#* New Partial Views will be rendered here *#
</div>
Then in the Action which handles this you can use the Get/Post/Redirect design pattern to put a new PartialView on the Page:
[HttpPost]
public ActionResult AddressBook(MyViewModel model)
{
// do stuff with model, then pass an Id?
// to the Action which renders the partial view
return RedirectToAction("AddRecord", new { id = model.Id });
}
public ActionResult AddRecord(int id)
{
MyChildModel model = new MyChildModel();
model.Id = id;
return PartialView("_ChildView", model);
}

$('#btnAddRecords').click(function(){
$.getJSON("/MyController/AddRecord", null
function (data) {
$('#divToAddRecords').append(data);
});
})
In Controller:
public JsonResult AddRecord()
{
...
var res = SerializeControl("~/Views/Folder/ChildView.cshtml", viewModel);
return Json(res, JsonRequestBehavior.AllowGet);
}
private string SerializeControl()
{
var control = new RazorView(ControllerContext, controlPath, null, false, null);
ViewData.Model = model;
var writer = new HtmlTextWriter(new StringWriter());
control.Render(new ViewContext(ControllerContext, control, ViewData, TempData, writer), writer);
string value = writer.InnerWriter.ToString();
return value;
}
And change so that button that adds records does not submit

Related

Change Data in DataTable with Select from Dropdownlist

I have a view with a Datatable, and I want to change the data every time I select a category from a drop-down list.
I want to only display the albums from the selected category, or all albums from all categories, using Ajax and jQuery. The drop-down list must be placed above the table.
Here is my code:
#using System.Collections.Generic;
#using CakeStore.App.Areas.Admin.Models.Albums;
#using CakeStore.App.Services.Contracts;
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#inject IAlbumService AlbumService
#{ ViewData["Title"] = "Category Albums";
Layout = "~/Areas/Admin/Views/Shared/_AdminLayout.cshtml";
var albums = ViewBag.CategoryAlbums as List<AlbumTableViewModel>;
}
<h1 class="text-center text-header-page">Category Albums</h1>
<hr class="hr-admin-divider" />
<div class="form-group">
<a class="btn button-black-white d-flex justify-content-left" href="/Admin/Albums/Create">Create</a>
</div>
<hr class="hr-admin-divider" />
<div class="d-flex">
<table class="table table-striped table-hover" id="myTable">
<tr>
<th>#</th>
<th>Name</th>
<th>Category</th>
<th></th>
<th></th>
<th></th>
</tr>
#for (int i = 0; i < albums.Count(); i++) {
<tr>
<td class="col-md-1">#albums[i].Id</td>
<td class="col-md-3">#albums[i].Name</td>
<td class="col-md-2">#albums[i].Category</td>
<td><a class="btn button-table-edit" href="/Admin/Albums/Edit?id=#albums[i].Id">EDIT</a></td>
<td><a class="btn button-table-delete d-flex justify-content-right" href="/Admin/Albums/Delete?id=#albums[i].Id">DELETE</a></td>
<td><a class="btn button-table-view d-flex justify-content-right" href="/Admin/Products/CategoryAlbums?id=#albums[i].Id">PRODUCTS</a></td>
</tr>
}
</table>
</div>
<div class="row d-flex align-items-end flex-column" style="font-size:12px">
<a class="btn-link pull-right col-lg-2" asp-controller="Categories" asp-action="Category">Back to Categories</a>
</div>
#section Scripts {
<partial name="_ValidationScriptsPartial" />
}
You could use the Partial View ,I made the demo ,you could refer to it
Use ajax to call the GetCityList method to get the data corresponding to the countryId passed .
<div class="form-group">
<label class="col-form-label">Country</label>
<select class="form-control" asp-items="#ViewBag.Country" id="selectlist">
<option>All</option>
</select>
</div>
<div class="form-group" id="cityListWrapper">
<partial name="_CityListPartial" model="#ViewBag.City" />
</div>
#section Scripts
{
<script type="text/javascript">
$("#selectlist").change(function () {
var countryId = $("#selectlist").val();
$.ajax
({
type: "GET",
url: "/Countries/GetCityList?CountryId="+countryId,
success: function (result) {
$("#cityListWrapper").html(result)
}
});
});
</script>
}
Initial rendering the main view , show all albums when not selected
public async Task<IActionResult> Index()
{
ViewBag.Country = new SelectList(_context.Country, "Id", "CountryName");
ViewBag.City = _context.City.ToList();
return View();
}
The GetCityList action ,render the partial view using a statement that returns different values
[HttpGet]
public async Task<IActionResult> GetCityList(int? countryId)
{
if (countryId == null)
{
var CityList = await _context.City.ToListAsync();
return PartialView("_CityListPartial", CityList);
}
var Cities =await _context.City.Where(c => c.Country.Id == countryId).ToListAsync();
return PartialView("_CityListPartial", Cities);
}
How it works

View values not returned to the controller action

Can anyone tell whats wrong with my view? my model values is displayed correctly in my view but it is not returned to the controller action. public ActionResult DeleteConfirmed(ClientModel contacts) my ClientModel is returned null.
View:
#model ContactManager.Models.ClientModel
#{
ViewBag.Title = "Delete Information";
}
<h2>Delete Information</h2>
<h3>Are you sure you want to delete this?</h3>
<fieldset>
<legend>Details</legend>
<div class="display-label">ID</div>
<div class="display-field">
#Html.DisplayFor(model => model.CanaClie0012.Client00130012)
</div>
<div class="display-label">Name</div>
<div class="display-field">
#Html.DisplayFor(model => model.Clientes0013.Nombre0013)
</div>
<div class="display-label">Contact Number</div>
<div class="display-field">
#Html.DisplayFor(model => model.CanaClie0012.Direcc0012)
</div>
<div class="display-label">Country</div>
<div class="display-field">
#Html.DisplayFor(model => model.CanaClie0012.F1Pais00200012)
</div>
</fieldset>
#using (Html.BeginForm()) {
<p>
<input type="submit" value="Delete" /> |
#Html.ActionLink("Back to List", "Index")
</p>
}
Controller Action:
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(ClientModel contacts)
{
contacts.Clientes0013.Client0013 = contacts.CanaClie0012.Client00130012;
contacts.Clientes0013.F1Pais00200013 = contacts.CanaClie0012.F1Pais00200012;
Clientes0013 clientes0013 = db.Clientes0013.Find(contacts.Clientes0013.Client0013, contacts.Clientes0013.F1Pais00200013);
db.Clientes0013.Remove(clientes0013);
db.SaveChanges();
return RedirectToAction("Index");
}
1. Keep the helpers inside the Form like below.
#using (Html.BeginForm("ActionName", "ControllerName", FormMethod.Post, null))
{
#Html.DisplayFor(i => i.PropertyName);
<input type="submit" name="Submit" value="Submit" />
}
2. In order to Submit the form and send the model in Post Action Method, you have to use a Hidden Field along with each DisplayFor Helper.
#using (Html.BeginForm("ActionName", "ControllerName", FormMethod.Post, null))
{
#Html.HiddenFor(i => i.PropertyName);
#Html.DisplayFor(i => i.PropertyName);
<input type="submit" name="Submit" value="Submit" />
}
3. You will not be able to see the Model values in Post Action Method when the View is like below..
#Html.HiddenFor(i => i.PropertyName);
#Html.DisplayFor(i => i.PropertyName);
#using (Html.BeginForm("ActionName", "ControllerName", FormMethod.Post, null))
{
<input type="submit" name="Submit" value="Submit" />
}
This is because you are using DisplayFor for all your properties. DisplayFor will not send anything in a POST, it doesn't create an input.
You could add #Html.HiddenFor(model => model.CanaClie0012.Client00130012) , etc. to each one of your properties in order for your view to send anything back.

MVC3 razor view error Microsoft JScript runtime error: Object doesn't support property or method 'datepicker'`

I am trying to display a datepicker for my Html.EditorFor
To do this I created an EditorTemplate in my Views\Shared\EditorTemplate folder , Named it DateTime.cshtml
but it is not working ,instead I am getting error ---Microsoft JScript runtime error: Object doesn't support property or method 'datepicker'
Plz help me to fix this error
This is my razor view page
#model MyWebRole.ViewModels.ViewModelEvents
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset style="width:50%">
<legend>Event Details:</legend>
<div>
<table>
<tr>
<td>
#Html.EditorFor(model => model.vmStartDate)
#Html.ValidationMessageFor(model => model.vmStartDate)
</td>
</tr>
</table>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
and here is my DateTime.cshtml (pasted below)
#model System.DateTime?
<div class="editor-field">
#Html.TextBox("", String.Format("{0:MM/dd/yyyy}",(Model == DateTime.MinValue)? null : Model), new { #class="text"})
</div>
<script type="text/javascript">
$(document).ready(function () {
$("##ViewData.ModelMetadata.PropertyName").datepicker({
changeMonth: true,
changeYear: true,
dateFormat: 'mm/dd/yy',
gotoCurrent: true
});
});
</script>
I am able to get datepicker working on another view
#model MyWebRole.Models.Events
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset style="width:50%">
<legend>Event Details:</legend>
<div>
<table>
<tr>
<td>
#Html.EditorFor(model => model.StartDate)
#Html.ValidationMessageFor(model => model.StartDate)
</td>
</tr>
</table>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
The difference between the two razor views is that
-->the first one( (datepicker not working) is using a ViewModel as model ie(mywebrole.ViewModels.EventViewModel)
--> and the second one is using the myWebrole.models.Events (datepicker working fine)
Is this an issue ?
Given that error, I think the problem is the selector. Instead of $("##ViewData.ModelMetadata.PropertyName"), try this one:
$("input.text").datepicker({ ...
(Alternatively, you could #Html.TextBoxFor(model => model) instead of #Html.TextBox, so that way the input would get id=PropertyName, and thus the selector should work).
Also, you're sure the script for the datepicker JQuery plugin loaded successfully on the page, right?

mvc3 partial views for search, validate, submit final results

I am creating a UI using MVC3 to generate a text file message based on user selections. User needs to find a patient by ID, then a provider by name from my db, and then initiate the creation of the text file. I have the message generator working if the right objects are passed to it (separate assembly).
I need some help understanding how to implement the search/select/clear logic, and the submission of results to call the generator. (New to MVC3).
I made partial views to display the search results, and I have the basic search results showing up on my Index view.
Issues:
My provider search returns a list of providers by last name & first name, and I need my user to select one, if there are more than one by the name.
How do I put these partial views inside a third, to send their results?
How can I make it possible to clear results in the partials? How do I make sure that I have a valid value in the partials before I send the result?
Any direction would be helpful. Thanks.
Here's my HomeController:
public class HomeController : Controller
{
private CrdDatabase db = new CrdDatabase(ConfigurationManager.ConnectionStrings["connectionString_CRD_TEST"].ConnectionString);
public PartialViewResult PatientSearch(string clinicNumber)
{
var patient = db.GetCRDPatientInformation(clinicNumber);
if (patient != null)
{
return PartialView("_PatientSearchResult", patient);
}
// need to determine how to return an error message/validation message.
return PartialView("_PartialClear");
}
public PartialViewResult ProviderSearch(string lastName, string firstname)
{
var providerList = db.GetCRDProviderList(lastName, firstname);
if (providerList.Count < 1)
{
return PartialView("_ProviderSearchResults", providerList);
}
return PartialView("_PartialClear");
}
public ActionResult Index()
{
return View();
}
}
Here is the _PatientSearchResult.cshtml partial view:
#model Objects.CRDPatientInfo
<table id="searchResults">
<tr>
<th>
Clinic Number
</th>
<th>
Last Name
</th>
<th>
First Name
</th>
<th>
Middle Name
</th>
<th>
Date of Birth
</th>
<th>
Admin Gender
</th>
</tr>
<tr>
<td>
#Model.clinic_number
</td>
<td>
#Model.pat_name_last
</td>
<td>
#Model.pat_name_first
</td>
<td>
#Model.pat_name_mid
</td>
<td>
#Model.pat_birth_date
</td>
<td>
#Model.pat_gender_code
</td>
</tr>
</table>
The _ProviderSearchResults.cshtml is similar, except it loops through the list in the model.
Here is my Index.cshtml, so far:
#{
ViewBag.Title = "Muse Orders Home Page";
}
<h2>#ViewBag.Message</h2>
#using (Ajax.BeginForm("PatientSearch", "Home", new AjaxOptions
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "searchPatientResults"
}))
{
<text>Clinic Number:</text>
<input type="text" name="clinicNumber" />
<input type="submit" name="submitButton" value="Search" />
<input type="submit" name="submitButton" value="Clear" />
}
<table id="searchPatientResults">
</table>
#using (Ajax.BeginForm("ProviderSearch", "Home", new AjaxOptions{
HttpMethod = "GET",
InsertionMode= InsertionMode.Replace,
UpdateTargetId= "searchProviderResults"
}))
{
<text>Provider Last Name:</text>
<input type="text" name="lastName" />
<text>Provider First Name:</text>
<input type="text" name="firstName" />
<input type="submit" name="submitButton" value="Search" />
<input type="submit" name="submitButton" value="Clear" />
}
<table id="searchProviderResults">
</table>
#using (Ajax.BeginForm("GenerateOrder", "Home", new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "generateOrder"
}))
{
<input type="hidden" name="patient" />
<input type="hidden" name="provider" />
<input type="submit" name="submitButton" value="GenerateOrder" />
<input type="submit" name="submitButton" value="Clear" />
}
<table id="generateOrder">
</table>

Nullable value in Edit Action

I have an Edit form, and have a problem when saving the result.
View:
<div class="editor-label">
#Html.LabelFor(model => model.LoginModel.Uzytkownik)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LoginModel.Uzytkownik)
#Html.ValidationMessageFor(model => model.LoginModel.Uzytkownik)
</div>
Model:
namespace Restauracja.Models
{
public class pracownikModel
{
public LoginModel LoginModel { get; set; }
public uzytkownikModel uzytkownikModle { get; set; }
public pracownikModel() {
LoginModel = new LoginModel();
uzytkownikModle = new uzytkownikModel();
}
}
public class LoginModel
{
[Required]
public string Uzytkownik { get; set; }
[Required]
public string Haslo { get; set; }
public string Konto { get; set; }
}
public class uzytkownikModel
{
[Required]
public string imie { get; set; }
....
}
}
Controller:
[HttpGet]
public ActionResult Edit(int LoginID)
{
pracownikModel prac = new pracownikModel();
var pr = (from p in baza.Logowanies where LoginID == p.LoginID select p).First();
prac.LoginModel.Uzytkownik = pr.Login;
return View(prac);
}
[HttpPost]
public ActionResult Edit(int LoginID, pracownikModel prac)
{
var xxx = (from z in baza.Logowanies where LoginID == z.LoginID select z).Single();
xxx.Login = prac.LoginModel.Uzytkownik;
baza.SubmitChanges();
return RedirectToAction("Index", "Foo");
}
Function with [HttpGet] is working properly, showing result from database. The problem is with second function... prac is null... So this cannot work because I can't write null to the database. I don't know how to solve this problem.
I would recommend you to use only standard ASCII letters and numbers when naming your variables and classes. The default model binder uses those names when trying to bind the properties from the POST request. Also since those property names are used as name and id attribute of the input elements in the HTML you end up with invalid HTML according to the specification which states:
ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods (".").
So you should not use extended ASCII or unicode symbols such as ł and ż. Replace them with their corresponding ASCII character and the default model binder will be able to correct fetch the values.
UPDATE:
After looking at the sample code you sent me in your Edit view you currently have 3 forms:
#model Restauracja.Models.pracownikModel
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Edit</legend>
<div class="editor-label">
#Html.LabelFor(model => model.LoginModel.Uzytkownik)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LoginModel.Uzytkownik)
#Html.ValidationMessageFor(model => model.LoginModel.Uzytkownik)
</div>
</fieldset>
}
<table id="nostyle">
<tr>
<td>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<input type="submit" value="Save" />
}
</td>
<td>
#using (Html.BeginForm("Anuluj", "Pracownik", FormMethod.Post, new { id = "AnulujForm" }))
{
<input id="Anuluj" type="submit" value="Cancel" />
}
</td>
</tr>
</table>
The first form is the only one that contains input fields for your model. So it is by submitting only the first form that you can expect to populate some of the properties of your model in the POST action. Unfortunately this first form doesn't have a submit button so you cannot submit it. The second and third form contain submit buttons but they do not contain any input field so submitting them will leave the model totally blank.
So what you need here is to move the Save submit button inside the first form:
#model Restauracja.Models.pracownikModel
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Edit</legend>
<div class="editor-label">
#Html.LabelFor(model => model.LoginModel.Uzytkownik)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LoginModel.Uzytkownik)
#Html.ValidationMessageFor(model => model.LoginModel.Uzytkownik)
</div>
</fieldset>
#:<table id="nostyle">
#:<tr>
#:<td>
<input type="submit" value="Save" />
#:</td>
}
<td>
#using (Html.BeginForm("Anuluj", "Pracownik", FormMethod.Post, new { id = "AnulujForm" }))
{
<input id="Anuluj" type="submit" value="Cancel" />
}
</td>
</tr>
</table>
or since the Cancel submit button posts currently to a controller action tat performs a redirect you could simply replace it with an anchor which will redirect:
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Edit</legend>
<div class="editor-label">
#Html.LabelFor(model => model.LoginModel.Uzytkownik)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LoginModel.Uzytkownik)
#Html.ValidationMessageFor(model => model.LoginModel.Uzytkownik)
</div>
</fieldset>
<table id="nostyle">
<tr>
<td>
<input type="submit" value="Save" />
</td>
<td>
#Html.ActionLink("Cancel", "zarzadzaj_pracownikami", "Pracownik")
</td>
</tr>
</table>
}

Resources