In this article we will see how to create a dynamic grid using knockout js and how to add a row wise validation by using knockout validation. We also look how add, insert and delete a row in a grid.
What we will achieve at final:
1) Dynamically adding and inserting a row in grid and also deletion of row from grid.
2) Validation by using Knockout Validation api.
3) Generating json of records.
Our final output should be something like below:
1) If you click on Insert, it will add new record above the selected row likewise excels.
2) If you click on Add New Row, it will add new row at the bottom of the grid.
3) Now when you press Save it will validate all the row and notify by highlighting the border of the controls and if all the data validation is success it will generate json for you.
Now follow me step by step to achieve the above output:
1) Reference the following script files:
a) Jquery
b) Knockoutjs
c) Knockout validation
d) Bootstrap (optional)
<script src="Scripts/jquery-2.1.3.min.js" type="text/javascript"></script>
<script src="Scripts/knockout-3.2.0.js" type="text/javascript"></script>
<script src="Scripts/knockout.validation.min.js" type="text/javascript"></script>
<link href="Content/bootstrap.min.css" rel="stylesheet" type="text/css" />
2) Add this style part for highlighting the border of controls in case of validation failed:
<style>
.required-field
{
border:2px solid red;
}
</style>
3) Now create a script file or script section in a page and replace the script with the below given script:
<script>
$(function () {
var vm = function () {
var self = this;
// contains the list of row
self.list = ko.observableArray();
// for identifying the current added or inserted row
self.current = ko.observable();
// contains the list of countries
self.countries = ko.observableArray([{
id: 1,
name: "India"
},{
id: 2,
name: "Australlia"
}
]);
// contains the list of states
self.states = ko.observableArray([{
id: 1,
countryid: 1,
name: "Uttar Pradesh"
},{
id: 2,
countryid: 1,
name: "Delhi"
},{
id: 3,
countryid: 2,
name: "Sydney"
},{
id: 4,
countryid: 2,
name: "Melbourne"
}
]);
// will set when error need to show
self.showErrors = ko.observable(false);
// function for adding a new row in a table
self.addRow = function(order) {
var obj = {
Order: ko.observable(order),
FirstName: ko.observable().extend({ required: true }),
LastName: ko.observable().extend({ required: true }),
Country: ko.observable().extend({ required: true }),
State: ko.observable().extend({ required: true }),
ContactNo: ko.observable().extend({ required: true }),
Designation: ko.observable().extend({ required: true }),
Countries: self.countries()
};
// return list of errors from an object
obj.errors = ko.validation.group(obj);
// display an error for each fields of an object
obj.showerror = function (item) {
if (!item.isValid() && obj.showErrors()) {
return true;
}
else {
return false;
}
};
// computed function return filtered stated on the basis of country choosen
obj.States = ko.computed(function() {
if(obj.Country()) {
var list = ko.utils.arrayFilter(self.states(), function(item) {
return (item.countryid == obj.Country());
});
return list;
}
return [];
});
self.list.push(obj);
self.current(obj);
};
//calls on click of Add New Row
self.addNew = function () {
self.addRow((self.list().length + 1));
}
//calls on click of Insert
self.insert = function (obj) {
self.addRow(obj.Order());
// arranging list after inserting row in between of a grid
obj.Order(obj.Order() + 1);
$.each(self.list(), function(i, item) {
if(item.Order() >= obj.Order() && obj != item) {
item.Order(item.Order() + 1);
}
});
};
// calls on click of Delete
self.delete = function (obj) {
self.list.remove(obj);
// arranging list after deleting row from in between of a grid
$.each(self.list(), function(i, item) {
if(item.Order() >= obj.Order()) {
item.Order(item.Order() - 1);
}
});
};
// return sorted list on the basis of Order field
self.sortedlist = ko.computed(function() {
return self.list().sort(function (left, right) {
return left.Order() == right.Order() ? 0 : left.Order() < right.Order() ? -1 : 1
});
});
// calls on click of save
self.save = function() {
var isValid = true;
self.showErrors(true);
$.each(self.list(), function(i, item) {
if(item.errors().length > 0) {
isValid = false;
}
});
if(isValid) {
//generating json of records
alert(ko.toJSON(self.sortedlist));
}
else {
//setting focus in required field
$(".required-field").first().focus();
}
};
};
//initializing knockout validation
ko.validation.init({
registerExtenders: true,
messagesOnModified: true,
insertMessages: false
});
var viewModel = new vm();
ko.applyBindings(viewModel);
});
</script>
I had explained a use of every object and function by commenting above of each. Please read it, I hope u got it easily.
4) Now in the body section of html create a table and a paragraph by using following script:
<table class="table table-bordered">
<thead>
<tr>
<th>
S. No.
</th>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Country
</th>
<th>
State
</th>
<th>
Contact No
</th>
<th>
Designation
</th>
<th>
</th>
</tr>
</thead>
<tbody data-bind="foreach: { data: sortedlist, as: 'row' }">
<tr data-bind="style: { backgroundColor: row == $parent.current() ? '#E5E5E5': '' }">
<td data-bind="text:Order">
</td>
<td>
<input type="text" data-bind="value:FirstName, css:{'required-field':row.showerror(row.FirstName)}, valueUpdate: 'afterkeydown'" />
</td>
<td>
<input type="text" data-bind="value:LastName, css:{'required-field':row.showerror(row.LastName)}" />
</td>
<td>
<select data-bind="options:Countries,
optionsText: 'name',
optionsValue: 'id',
value:Country,
optionsCaption: '--Select Country--',
css:{'required-field':row.showerror(row.Country)}">
</select>
</td>
<td>
<select type="text" data-bind="options:States,
optionsText: 'name',
optionsValue: 'id',
value: State,
optionsCaption: '--Select State--',
css:{'required-field':row.showerror(row.State)}">
</select>
</td>
<td>
<input type="text" data-bind="value:ContactNo,css:{'required-field':row.showerror(row.ContactNo)}" />
</td>
<td>
<input type="text" data-bind="value:Designation,css:{'required-field':row.showerror(row.Designation)}" />
</td>
<td>
<input type="button" data-bind="event: { click: $parent.insert }" value="Insert" />
<input type="button" data-bind="event: { click: $parent.delete }" value="Delete" />
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="8" align="right">
<input type="button" data-bind="event: { click: addNew }" value="Add New Row" />
</td>
</tr>
</tfoot>
</table>
<p class="text-right col-md-12">
<input type="submit" data-bind="event: { click: save }" value="Save" />
</p>
Now you can browse the page and see the output. I hope it will give same output as I shown in above two screenshots.
Thanks for reading this article. If you have any doubts or suggestion, please enter by using comment box.
No comments:
Post a Comment