|
Introduction
In one of the previous article, I have explained how to show master-details data in asp.net MVC application with collapse / expand option and also I have explained how we can show master-details data in report viewer control in asp.net webform application. But Sometimes we need to create master details entry form in the single page, like Order and order details. Here we will see, how we can create master details entry form in a single page in asp.net MVC application.Steps :
Step - 1 : Create New Project.
Go to File > New > Project > Select asp.net MVC4 web application > Entry Application Name > Click OK > Select Basic > Select view engine Razor > OKStep-2: Add a Database.
Go to Solution Explorer > Right Click on App_Data folder > Add > New item > Select SQL Server Database Under Data > Enter Database name > Add.Step-3: Create table for Save data.
Here I will create 2 table (as below). 1 for save master record (Order) and another for save details record (order items).Open Database > Right Click on Table > Add New Table > Add Columns > Save > Enter table name > Ok.
Order
Step-4: Add Entity Data Model.
Go to Solution Explorer > Right Click on Project name form Solution Explorer > Add > New item > Select ADO.net Entity Data Model under data > Enter model name > Add.A popup window will come (Entity Data Model Wizard) > Select Generate from database > Next >
Chose your data connection > select your database > next > Select tables > enter Model Namespace > Finish.
Step-5: Create a view model.
Here we will create a ViewModel. First we will add a new folder named "ViewModel" and inside this folder we will create a class as belowusing System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MvcMasterDetails.Models { public class OrderVM { public string OrderNo { get; set; } public DateTime OrderDate { get; set; } public string Description { get; set; } public List<OrderDetail> OrderDetails {get;set;} } }
Step-6: Create a Controller.
Go to Solution Explorer > Right Click on Controllers folder form Solution Explorer > Add > Controller > Enter Controller name > Select Templete "empty MVC Controller"> Add.Here I have created a controller "HomeController"
Step-7: Add new action into your controller for Get Method
Here I have added "Index" Action into "Home" Controller. Please write this following codepublic ActionResult Index() { return View(); }
Step-8: Add view for your Action & design.
Right Click on Action Method (here right click on Index action) > Add View... > Enter View Name > Select View Engine (Razor) > Add.HTML Code
@{ ViewBag.Title = "Index"; } <h2>Master Details entry form</h2> <div class="container" style="max-width:640px"> <div class="master"> <h4>Order details</h4> <table> <tr> <td>Order No</td> <td> <input type="text" id="orderNo" /> <span class="error">Order no required</span> </td> <td>Order Date</td> <td> <input type="text" id="orderDate" /> <span class="error">Valid order date required (ex. MM-dd-yyyy)</span> </td> </tr> <tr> <td>Description</td> <td colspan="3"> <textarea id="description" style="width:100%"></textarea> </td> </tr> </table> </div> <div class="details"> <h4>Order Items</h4> <table width="100%"> <tr> <td>Item Name</td> <td>Quantity</td> <td>Rate</td> <td> </td> </tr> <tr> <td> <input type="text" id="itemName" /> <span class="error">Item name required</span> </td> <td> <input type="text" id="quantity" /> <span class="error">Valid quantity required</span> </td> <td> <input type="text" id="rate" /> <span class="error">Valid rate required</span> </td> <td> <input type="button" id="add" value="add" /> </td> </tr> </table> <div id="orderItems" class="tablecontainer"> </div> <div style="padding:10px 0px; text-align:right"> <input id="submit" type="button" value="Save" style="padding:10px 20px" /> </div> </div> </div>
Step-9: Add jquery code
Jquery Code<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script> <script> //Date Picker $(function () { $('#orderDate').datepicker({ dateFormat : 'mm-dd-yy' }); }); $(document).ready(function () { var orderItems = []; //Add button click function $('#add').click(function () { //Check validation of order item var isValidItem = true; if ($('#itemName').val().trim() == '') { isValidItem = false; $('#itemName').siblings('span.error').css('visibility', 'visible'); } else { $('#itemName').siblings('span.error').css('visibility', 'hidden'); } if (!($('#quantity').val().trim() != '' && !isNaN($('#quantity').val().trim()))) { isValidItem = false; $('#quantity').siblings('span.error').css('visibility', 'visible'); } else { $('#quantity').siblings('span.error').css('visibility', 'hidden'); } if (!($('#rate').val().trim() != '' && !isNaN($('#rate').val().trim()))) { isValidItem = false; $('#rate').siblings('span.error').css('visibility', 'visible'); } else { $('#rate').siblings('span.error').css('visibility', 'hidden'); } //Add item to list if valid if (isValidItem) { orderItems.push({ ItemName: $('#itemName').val().trim(), Quantity: parseInt($('#quantity').val().trim()), Rate: parseFloat($('#rate').val().trim()), TotalAmount: parseInt($('#quantity').val().trim()) * parseFloat($('#rate').val().trim()) }); //Clear fields $('#itemName').val('').focus(); $('#quantity,#rate').val(''); } //populate order items GeneratedItemsTable(); }); //Save button click function $('#submit').click(function () { //validation of order var isAllValid = true; if (orderItems.length == 0) { $('#orderItems').html('<span style="color:red;">Please add order items</span>'); isAllValid = false; } if ($('#orderNo').val().trim() == '') { $('#orderNo').siblings('span.error').css('visibility', 'visible'); isAllValid = false; } else { $('#orderNo').siblings('span.error').css('visibility', 'hidden'); } if ($('#orderDate').val().trim() == '') { $('#orderDate').siblings('span.error').css('visibility', 'visible'); isAllValid = false; } else { $('#orderDate').siblings('span.error').css('visibility', 'hidden'); } //Save if valid if (isAllValid) { var data = { OrderNo: $('#orderNo').val().trim(), OrderDate: $('#orderDate').val().trim(), //Sorry forgot to add Description Field Description : $('#description').val().trim(), OrderDetails : orderItems } $(this).val('Please wait...'); $.ajax({ url: '/Home/SaveOrder', type: "POST", data: JSON.stringify(data), dataType: "JSON", contentType: "application/json", success: function (d) { //check is successfully save to database if (d.status == true) { //will send status from server side alert('Successfully done.'); //clear form orderItems = []; $('#orderNo').val(''); $('#orderDate').val(''); $('#orderItems').empty(); } else { alert('Failed'); } $('#submit').val('Save'); }, error: function () { alert('Error. Please try again.'); $('#submit').val('Save'); } }); } }); //function for show added items in table function GeneratedItemsTable() { if (orderItems.length > 0) { var $table = $('<table/>'); $table.append('<thead><tr><th>Item</th><th>Quantity</th><th>Rate</th><th>Total</th><th></th></tr></thead>'); var $tbody = $('<tbody/>'); $.each(orderItems, function (i, val) { var $row = $('<tr/>'); $row.append($('<td/>').html(val.ItemName)); $row.append($('<td/>').html(val.Quantity)); $row.append($('<td/>').html(val.Rate)); $row.append($('<td/>').html(val.TotalAmount)); var $remove = $('<a href="#">Remove</a>'); $remove.click(function (e) { e.preventDefault(); orderItems.splice(i, 1); GeneratedItemsTable(); }); $row.append($('<td/>').html($remove)); $tbody.append($row); }); console.log("current", orderItems); $table.append($tbody); $('#orderItems').html($table); } else { $('#orderItems').html(''); } } }); </script>Complete HTML Code
@{ ViewBag.Title = "Index"; } <h2>Master Details entry form</h2> <div class="container" style="max-width:640px"> <div class="master"> <h4>Order details</h4> <table> <tr> <td>Order No</td> <td> <input type="text" id="orderNo" /> <span class="error">Order no required</span> </td> <td>Order Date</td> <td> <input type="text" id="orderDate" /> <span class="error">Valid order date required (ex. MM-dd-yyyy)</span> </td> </tr> <tr> <td>Description</td> <td colspan="3"> <textarea id="description" style="width:100%"></textarea> </td> </tr> </table> </div> <div class="details"> <h4>Order Items</h4> <table width="100%"> <tr> <td>Item Name</td> <td>Quantity</td> <td>Rate</td> <td> </td> </tr> <tr> <td> <input type="text" id="itemName" /> <span class="error">Item name required</span> </td> <td> <input type="text" id="quantity" /> <span class="error">Valid quantity required</span> </td> <td> <input type="text" id="rate" /> <span class="error">Valid rate required</span> </td> <td> <input type="button" id="add" value="add" /> </td> </tr> </table> <div id="orderItems" class="tablecontainer"> </div> <div style="padding:10px 0px; text-align:right"> <input id="submit" type="button" value="Save" style="padding:10px 20px" /> </div> </div> </div> <link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css"> @section Scripts{ <script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script> <script> //Date Picker $(function () { $('#orderDate').datepicker({ dateFormat : 'mm-dd-yy' }); }); $(document).ready(function () { var orderItems = []; //Add button click function $('#add').click(function () { //Check validation of order item var isValidItem = true; if ($('#itemName').val().trim() == '') { isValidItem = false; $('#itemName').siblings('span.error').css('visibility', 'visible'); } else { $('#itemName').siblings('span.error').css('visibility', 'hidden'); } if (!($('#quantity').val().trim() != '' && !isNaN($('#quantity').val().trim()))) { isValidItem = false; $('#quantity').siblings('span.error').css('visibility', 'visible'); } else { $('#quantity').siblings('span.error').css('visibility', 'hidden'); } if (!($('#rate').val().trim() != '' && !isNaN($('#rate').val().trim()))) { isValidItem = false; $('#rate').siblings('span.error').css('visibility', 'visible'); } else { $('#rate').siblings('span.error').css('visibility', 'hidden'); } //Add item to list if valid if (isValidItem) { orderItems.push({ ItemName: $('#itemName').val().trim(), Quantity: parseInt($('#quantity').val().trim()), Rate: parseFloat($('#rate').val().trim()), TotalAmount: parseInt($('#quantity').val().trim()) * parseFloat($('#rate').val().trim()) }); //Clear fields $('#itemName').val('').focus(); $('#quantity,#rate').val(''); } //populate order items GeneratedItemsTable(); }); //Save button click function $('#submit').click(function () { //validation of order var isAllValid = true; if (orderItems.length == 0) { $('#orderItems').html('<span style="color:red;">Please add order items</span>'); isAllValid = false; } if ($('#orderNo').val().trim() == '') { $('#orderNo').siblings('span.error').css('visibility', 'visible'); isAllValid = false; } else { $('#orderNo').siblings('span.error').css('visibility', 'hidden'); } if ($('#orderDate').val().trim() == '') { $('#orderDate').siblings('span.error').css('visibility', 'visible'); isAllValid = false; } else { $('#orderDate').siblings('span.error').css('visibility', 'hidden'); } //Save if valid if (isAllValid) { var data = { OrderNo: $('#orderNo').val().trim(), OrderDate: $('#orderDate').val().trim(), //Sorry forgot to add Description Field Description : $('#description').val().trim(), OrderDetails : orderItems } $(this).val('Please wait...'); $.ajax({ url: '/Home/SaveOrder', type: "POST", data: JSON.stringify(data), dataType: "JSON", contentType: "application/json", success: function (d) { //check is successfully save to database if (d.status == true) { //will send status from server side alert('Successfully done.'); //clear form orderItems = []; $('#orderNo').val(''); $('#orderDate').val(''); $('#orderItems').empty(); } else { alert('Failed'); } $('#submit').val('Save'); }, error: function () { alert('Error. Please try again.'); $('#submit').val('Save'); } }); } }); //function for show added items in table function GeneratedItemsTable() { if (orderItems.length > 0) { var $table = $('<table/>'); $table.append('<thead><tr><th>Item</th><th>Quantity</th><th>Rate</th><th>Total</th><th></th></tr></thead>'); var $tbody = $('<tbody/>'); $.each(orderItems, function (i, val) { var $row = $('<tr/>'); $row.append($('<td/>').html(val.ItemName)); $row.append($('<td/>').html(val.Quantity)); $row.append($('<td/>').html(val.Rate)); $row.append($('<td/>').html(val.TotalAmount)); var $remove = $('<a href="#">Remove</a>'); $remove.click(function (e) { e.preventDefault(); orderItems.splice(i, 1); GeneratedItemsTable(); }); $row.append($('<td/>').html($remove)); $tbody.append($row); }); console.log("current", orderItems); $table.append($tbody); $('#orderItems').html($table); } else { $('#orderItems').html(''); } } }); </script> } <style> /*Adding some css for looks good*/ span.error { display:block; visibility:hidden; color:red; font-size:90%; } /*css for table*/ .container td { vertical-align: top; } .tablecontainer table { width: 100%; border-collapse: collapse; border-top: 1px solid #BFAEAE; border-right: 1px solid #BFAEAE; } .tablecontainer th { border-bottom: 2px solid #BFAEAE !important; } .tablecontainer th, .tablecontainer td { text-align: left; border-left: 1px solid #BFAEAE; padding: 5px; border-bottom: 1px solid #BFAEAE; } .ui-widget { font-size:12px !important; } </style>
Step-10: Add new action into your controller for save order and order details (POST Method)
Here I have added "SaveOrder" Action into "Home" Controller. Please write this following code//Post action for Save data to database [HttpPost] public JsonResult SaveOrder(OrderVM O) { bool status = false; if (ModelState.IsValid) { using (MyDatabaseEntities dc = new MyDatabaseEntities()) { Order order = new Order { OrderNo = O.OrderNo, OrderDate = O.OrderDate, Description = O.Description }; foreach (var i in O.OrderDetails) { // // i.TotalAmount = order.OrderDetails.Add(i); } dc.Orders.Add(order); dc.SaveChanges(); status = true; } } else { status = false; } return new JsonResult { Data = new { status = status} }; }