In my previous article "CRUD Operations Using Knockout in MVC Application - Part 1" we completed the work on the Model and Controller classes, this article will show the functionality of the View Class.
You can download the code for this application from here: "CRUD Operations Using Knockout".
Step 1. As in the previous article, I told you that I added a View class to the View Folder so I am working on the same class.
Our View Class is divided into two parts, the first part is the Knockout Coding and the second part consists of HTML controls declared and bound to the Controller and Model using Knockout. So, we will first work on the first part, in other words the Knockout part. First you need to add an external Knockout-2.2.0.JS and Knockout-2.2.0.debug.js file to your application then write this code:
<script src="~/Scripts/knockout-2.2.0.js"></script>
<script src="@Url.Content('~/Scripts/knockout-2.2.0.debug.js')" type="text/javascript"></script>
<script type="text/javascript">
function formatCurrency(value) {
return "$" + value.toFixed(2);
}
function ProductViewModel() {
var self = this;
self.Id = ko.observable("");
self.Title = ko.observable("");
self.Cost = ko.observable("");
self.Class = ko.observable("");
var Product = {
Id: self.Id,
Title: self.Title,
Cost: self.Cost,
Class: self.Class
};
self.Product = ko.observable();
self.Products = ko.observableArray();
$.ajax({
url: '@Url.Action("GetAllProducts", "Product")',
cache: false,
type: 'GET',
contentType: 'application/json; charset=utf-8',
data: {},
success: function (data) {
self.Products(data);
}
});
self.Total = ko.computed(function () {
var sum = 0;
var arr = self.Products();
for (var i = 0; i < arr.length; i++) {
sum += arr[i].Cost;
}
return sum;
});
self.create = function () {
if (Product.Title() !== "" && Product.Cost() !== "" && Product.Class() !== "") {
$.ajax({
url: '@Url.Action("AddProduct", "Product")',
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: ko.toJSON(Product),
success: function (data) {
self.Products.push(data);
self.Title("");
self.Cost("");
self.Class("");
}
}).fail(function (xhr, textStatus, err) {
alert(err);
});
} else {
alert('Please Enter All the Values !!');
}
};
self.delete = function (Product) {
if (confirm('Are you sure to Delete "' + Product.Title + '" product ??')) {
var id = Product.Id;
$.ajax({
url: '@Url.Action("AddProduct", "Product")',
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: ko.toJSON(id),
success: function (data) {
self.Products.remove(Product);
}
}).fail(function (xhr, textStatus, err) {
alert(err);
});
}
};
self.edit = function (Product) {
self.Product(Product);
};
self.change = function () {
var Product = self.Product();
$.ajax({
url: '@Url.Action("EditProduct", "Product")',
cache: false,
type: 'PUT',
contentType: 'application/json; charset=utf-8',
data: ko.toJSON(Product),
success: function (data) {
self.Products.removeAll();
self.Products(data);
self.Product(null);
alert("Record Updated Successfully");
}
}).fail(function (xhr, textStatus, err) {
alert(err);
});
};
self.reset = function () {
self.Title("");
self.Cost("");
self.Class("");
};
self.cancel = function () {
self.Product(null);
};
}
var viewModel = new ProductViewModel();
ko.applyBindings(viewModel);
</script>
Here in the first function, I have added a $ sign with the cost and also the cost will be shown in the decimal place, up to two values.
Then I declared Observables for ID, Class, Cost, Title, and Product. An Observable Array named Products was also created.
A computed function is created that will show the sum of all the Price values of all the Products.
The Create function will work when the user makes a new entry by clicking on the "Add" button. First, all three Textboxes will be empty, then the user needs to enter some values into all three of these Textboxes, if any TextBox is found empty then an error message will be shown that will ask to enter some value in all the Textboxes, then these entries will be added to the Products Array.
The Delete function will work on the ID of the Product, it will delete all the entries at that ID, if this function can't find the ID specified then an error message will be shown.
The Change function will use the edit function to edit the values of the product based on the ID of that product.
Towards the end, two more functions are created, named "reset" and "cancel"; reset will make all the TextBoxes empty and will allow the user to make new entries and the cancel button will cancel all the work done.
In the end, Binding is applied to the ViewModel.
Step 2. Now we will work on the second part of the View Class, in other words on the HTML part. Write the following code where the Script tag ends.
<div id="body">
<h2>CRUD Operations Using Knockout</h2>
<h3>Items List</h3>
<table id="products1" data-bind="visible: Products().length > 0">
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Class</th>
<th>Cost</th>
<th>Actions</th>
</tr>
</thead>
<tbody data-bind="foreach: Products">
<tr>
<td data-bind="text: Id"></td>
<td data-bind="text: Title"></td>
<td data-bind="text: Class"></td>
<td data-bind="text: formatCurrency(Cost)"></td>
<td>
<button data-bind="click: $root.edit">Edit</button>
<button data-bind="click: $root.delete">Delete</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td></td>
<td></td>
<td>Total :</td>
<td data-bind="text: formatCurrency($root.Total())"></td>
<td></td>
</tr>
</tfoot>
</table>
<br />
<div style="border-top: solid 2px #282828; width: 430px; height: 10px;"></div>
<div data-bind="if: Product">
<div>
<h2>Item Updation</h2>
</div>
<div>
<label for="productId" data-bind="visible: false">ID</label>
<label data-bind="text: Product().Id, visible: false"></label>
</div>
<div>
<label for="name">Title</label>
<input data-bind="value: Product().Title" type="text" title="Title" />
</div>
<div>
<label for="category">Class</label>
<input data-bind="value: Product().Class" type="text" title="Class" />
</div>
<div>
<label for="price">Cost</label>
<input data-bind="value: Product().Cost" type="text" title="Cost" />
</div>
<br />
<div>
<button data-bind="click: $root.change">Change</button>
<button data-bind="click: $root.cancel">Cancel</button>
</div>
</div>
<div data-bind="ifnot: Product()">
<div>
<h2>Add Item</h2>
</div>
<div>
<label for="name">Title</label>
<input data-bind="value: $root.Title" type="text" title="Title" />
</div>
<div>
<label for="category">Class</label>
<input data-bind="value: $root.Class" type="text" title="Class" />
</div>
<div>
<label for="price">Cost</label>
<input data-bind="value: $root.Cost" type="text" title="Cost" />
</div>
<br />
<div>
<button data-bind="click: $root.create">O.K</button>
<button data-bind="click: $root.reset">Reset</button>
</div>
</div>
</div>
Here I have created a table in which five columns will be used; first for the ID, the second for the Title, the third for the class, the fourth for the Price, and the last for Editing or Deleting the record. Headings are provided in a similar order.
After providing the headings, four <td> tags are used that are bound to the Id, Title, Class, and FormulatedCurrency(cost), so these <td> will show the data relevant to the bound Observable. Formulated Currency will provide the cost with the $ sign and decimal point assigned to it.
After creating the table I worked on the "Update" and "Add Item", in the first Div if the user clicks on the "Edit" button then all the records related to that ID will be shown in the Textboxes used in the first Div. At the end of the Textboxes, two buttons are used; the first button will update the old value with the new value and the other button will cancel the update.
If the user clicks on the "Add" button then the same Textboxes will insert new values into the Observable Array and they will be shown along with the other Product Details. Here also at the end of Textboxes, two Buttons are used, the first button will make a new entry in the already existing group of Products and the second button will reset all the Textboxes so that the user can enter new values into the Textboxes.
Now our application is created and is ready to be executed.
You can download the code of this application from here: "CRUD Operations Using Knockout".
Step 3. On running the application you will get output like this one.
Here I am clicking on the Edit button so that the updates can be done.
On clicking the "Edit" Button the If condition will get activated and below the Div will start showing the Update Div instead of the "Add New" Div. Here you can make changes and then click on the "Update" button, this will update the preceding products.
Now I want to delete a Product, so I click on the "Delete" button in front of each row, this will open a Popup to confirm whether you want to delete or not, if you click on the "Ok" Button then that Product will be deleted.