KnockOut ajax with MVC - javascript

This is My KnockOut Controller Class
public class KnockoutController : Controller
{
//
// GET: /Knockout/
private DataLayer data;
public KnockoutController()
{
data=new DataLayer();
}
public ActionResult Index()
{
return View();
}
public ActionResult Grid()
{
ArrayList rows = new ArrayList();
List<Category> categories = data.RetrivingCategories();
foreach (var category in categories)
{
rows.Add(new { Id = category.Id, cell = new object[] { category.Id,
category.Name } });
}
var jsonData = new
{
rows
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
}
And This is My Index View
#{
ViewBag.Title = "Test";
}
<h2>Index</h2>
<title></title>
<script src="~/Scripts/jquery-ui-1.8.20.js"></script>
<script src="~/Scripts/knockout-2.1.0.debug.js"></script>
<script src="~/Scripts/knockout-2.1.0.js"></script>
<link href="~/Content/Site.css" rel="stylesheet" />
<table class="table">
<tr>
<th>
Key
</th>
<th>
Value
</th>
<th></th>
</tr>
<tbody data-bind="foreach: lookupCollection">
<tr>
<td data-bind="text: Key"></td>
<td data-bind="text: Value"></td>
</tr>
</tbody>
</table>
<script>
viewModel = {
lookupCollection: ko.observableArray()
};
$(function () {
$.ajax({
type: "GET",
url: "#Url.Action("Grid", "Knockout")",
}).done(function (data) {
$(data).each(function (index, element) {
var mappedItem =
{
Id: ko.observable(element.id),
Key: ko.observable(element.name),
};
viewModel.lookupCollection.push(mappedItem);
});
ko.applyBindings(viewModel);
}).error(function (ex) {
alert("Error");
});
});
</script>``
I am Calling json data from this index view using ajax call method but it's not returning anything, Any problem on my Script Part, Please help me , i am new to the Knockout..

Try this
$(function () {
$.ajax({
type: "GET",
url: "#Url.Action("Grid","Knockout")",
}).done(function (data) {
$.each(data, function (index, element) {
var mappedItem = {
Id: ko.observable(element.id),
Key: ko.observable(element.name),
};
viewModel.lookupCollection.push(mappedItem);
});
ko.applyBindings(viewModel);
}).error(function (ex) {
alert("Error");
});
});
From the jQuery API docs,
The $.each() function is not the same as $(selector).each(), which is
used to iterate, exclusively, over a jQuery object. The $.each()
function can be used to iterate over any collection, whether it is an object or an array.

Related

How can I keep the selected rows of the table after calling the post method from submit button of a view

After calling the post method from the controller, the selected rows of the table is disappeared. I am trying to keep the selected rows as it is even after post method ReinstateEmployee() calling from the server. I am looking for someone help.
Here is the code
Model class I am keeping one more attribute to keep selected record
public class EmployeeReinstateVM
{
public List<string> selectedEmployeeId { get; set; }
}
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ReinstateEmployee(string btnsubmit, string btnActivate, EmployeeReinstateVM model)
{
var selectedEmployeeId = model.selectedEmployeeId;
return view()
}
View file
<style>
.selectable-row.selected {
background-color: #ddd;
}
</style>
<table class="table table-bordered table-light">
<tbody>
foreach (var item in Model.employees)
{
<tr class="selectable-row" employee-id="#item.EmployeeID">
<td>#item.EmployeeID</td>
<td>#item.DepotName</td>
<td>#item.EmployeeName</td>
<td>#item.EmpLeaveDate</td>
</tr>
}
</tbody>
</table>
<input type="hidden" id="selectedEmployeeId" name="selectedEmployeeId" value="">
<button type="submit" class="btn btn-primary form-control" id="btnSave" name="btnActivate" value="update">
List Leavers
</button>
<script type="text/javascript">
$(document).ready(function () {
var employeeIds = [];
$(".selectable-row").click(function () {
$(this).toggleClass("selected");
var employeeId = $(this).attr('employee-id');
if ($(this).hasClass("selected")) {
employeeIds.push(employeeId);
}
else {
employeeIds = employeeIds.filter(function (id) {
return id !== employeeId;
});
}
});
$("#btnSave").click(function () {
$("#selectedEmployeeId").val(employeeIds);
console.log($("#selectedEmployeeId").val());
});
});
}
</script>
return view()
If we use this, we will refresh the view.
I have a suggestion that you can use ajax to post your form, then we can keep the selected rows .
I test your code, but I cannot change the row background-color, and I change the color.You can refer to it.
In controller:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ReinstateEmployee(string btnsubmit, string btnActivate, EmployeeReinstateVM model)
{
//var selectedEmployeeId = model.selectedEmployeeId;
//return View();
return Json(btnsubmit);
}
In the view:
$("#btnSave").click(function () {
$("#selectedEmployeeId").val(employeeIds);
console.log($("#selectedEmployeeId").val());
$.ajax({
type: "POST",
url: "/Keepselected/ReinstateEmployee",
data: { "btnsubmit": "aa" },
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
success: function (response) {
alert(response);
}
});
});
result:

How received from server JSON use in Datatables Row details?

I have a table in my View project ASP MVC
#foreach (var items in Model)
{
<tr>
<th>
<input type="button" value="Assign" onclick="AssignButtonClicked(this)"
data-assigned-id="#items.ADUsersId" />
</th>
<th>#Html.DisplayFor(modelItem => items.DisplayName)</th>
<th>#Html.DisplayFor(modelItem => items.Company)</th>
<th>#Html.DisplayFor(modelItem => items.Department)</th>
<th>#Html.DisplayFor(modelItem => items.TelephoneNumber)</th>
</tr>
}
In the first post I pass Id to the function JS
function AssignButtonClicked(elem) {
var id = $(elem).data('assigned-id');
$.ajax({
url: '#Url.Action("Details", "Users")',
type: 'post',
//cache: false,
//async: true,
//data: { id: id }
data: { id:id }, // OR data: {id:1} => nothing work
dataType: "json",
success: function (data) {
alert(JSON.stringify(data));
},
error: function (xhr) {
alert('error');
}
})
};
Everything works well, I get the JSON data
Now, How I can use the Json data to make details row in Datatable? Here Example
You can use a little bit of jQuery to display the details of the record.Here's a complete example, hope it helps you:
Controller:
public class UsersController : Controller
{
public ActionResult Index()
{
var u1 = new User { ADUsersId = 1, DisplayName = "User 1", Company = "Company 1" };
var u2 = new User { ADUsersId = 2, DisplayName = "User 2", Company = "Company 2" };
var u3 = new User { ADUsersId = 3, DisplayName = "User 3", Company = "Company 3" };
var users = new List<User> { u1, u2, u3 };
return View(users);
}
[HttpPost]
public JsonResult Details(int id)
{
//Write your query to fetch the details of the user(mine is hardcoded for simplicity)
return Json(new {UserSurname="Surname " + id,UserNickName="Nickname " + id }, JsonRequestBehavior.AllowGet);
}
}
public class User
{
public int ADUsersId { get; set; }
public string DisplayName { get; set; }
public string Company { get; set; }
}
View:
#model IEnumerable<WebApplication7.Controllers.User>
#{
ViewBag.Title = "Index";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.3/jquery.min.js"></script>
<style type="text/css">
.detail{
border: 2px solid red;
}
</style>
<script type="text/javascript">
$('body').on('click', 'tr.detail', function () {
if(confirm("Are you sure you want to close the detail record?"))
{
$(this).remove();
}
});
function RemoveDetail(){
$('.table tr').each(function () {
var tr = $(this);
var isDetail = $(tr).hasClass("detail");
if (isDetail)
$(tr).remove();
});
}
function AssignButtonClicked(elem) {
var id = $(elem).data('assigned-id');
$.ajax({
url: '#Url.Action("Details", "Users")',
type: 'post',
data: { id: id },
dataType: "json",
success: function (data) {
debugger;
alert(JSON.stringify(data));
RemoveDetail();
var detailRow = "<tr class='detail'><td colspan='3'>Surname - " + data.UserSurname + "<br />Nickanme - " + data.UserNickName + "</td></tr>"
var currentRow = $(elem).parent().parent();
$(detailRow).insertAfter(currentRow);
},
error: function (xhr) {
alert('error');
}
});
};
</script>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.DisplayName)
</th>
<th>
#Html.DisplayNameFor(model => model.Company)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.DisplayName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Company)
</td>
<td>
<input type="button" value="Assign" onclick="AssignButtonClicked(this)" data-assigned-id="#item.ADUsersId" />
</td>
</tr>
}
</table>
Output:

Form is not Submitting any Value using Asp.Net MVC

In Model:
public int TeacherCourseAssignId { set; get; }
public int TeacherID { set; get; }
public decimal TeacherRemainingCredit { set; get; }
public int CourseId { set; get; }
public string CourseName { set; get; }
public decimal CourseCredit { set; get; }
In controller:
[HttpPost]
public ActionResult TeacherCourseAssign(int departmentId, int teacherId, int courseId)
{
ViewBag.Departments = GetDepartments();
return View();
}
public ActionResult SaveTeacherCourseAssign(TeacherCourseAssign teacherCourseAssign)
{
ViewBag.Departments = GetDepartments();
ViewBag.Message = teacherCourseAssignManager.Save(teacherCourseAssign);
ModelState.Clear();
return View();
}
public JsonResult SaveTeacheCourseAssign(TeacherCourseAssign teacherCourseAssign)
{
//Code
return Json(true, JsonRequestBehavior.AllowGet);
}
public JsonResult GetTeachersByDepartmentId(int deptId)
{
var teachers = GetTeacher();
var teacherList = teachers.Where(a => a.DepartmentId == deptId).ToList();
return Json(teacherList, JsonRequestBehavior.AllowGet);
}
public JsonResult GetCoursesByDepartmentId(int deptId)
{
var courses = GetCourses();
var courseList = courses.Where(a => a.DepartmentId == deptId).ToList();
return Json(courseList, JsonRequestBehavior.AllowGet);
}
public JsonResult GetTeachersInfoByTeacherId(int teacherId)
{
var teachers = GetTeacher();
var teacherInfo = teachers.Where(t => t.TeacherID == teacherId).ToList();
return Json(teacherInfo, JsonRequestBehavior.AllowGet);
}
public JsonResult GetCoursesInfoByCourseId(int courseId)
{
var courses = GetCourses();
var courseList = courses.Where(c => c.CourseId == courseId).ToList();
return Json(courseList, JsonRequestBehavior.AllowGet);
}
In View:
#model Last.Models.TeacherCourseAssign
#{
ViewBag.Title = "Teacher Course Assign";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Teacher Course Assign</h2>
<form method="POST" id="myForm">
<table>
<tr>
<td>
<label for="departmentId">Select Department</label>
</td>
<td>
<select name="departmentId" id="departmentId">
<option value="">Select...</option>
#foreach (var department in ViewBag.Departments)
{
<option value="#department.DeptId">#department.DeptName</option>
}
</select>
</td>
</tr>
<tr>
<td><label for="teacherId">Teacher</label></td>
<td>
<select name="teacherId" id="teacherId"></select>
</td>
</tr>
<tr>
<td>#Html.LabelFor(m => m.CreditToBeTaken)</td>
<td>#Html.TextBoxFor(m => m.CreditToBeTaken)</td>
</tr>
<tr>
<td>#Html.LabelFor(r => r.TeacherRemainingCredit)</td>
<td>
#Html.TextBoxFor(r => r.TeacherRemainingCredit)
</td>
</tr>
<tr>
<td><label for="courseId"></label></td>
<td>
<select name="courseId" id="courseId"></select>
</td>
</tr>
<tr>
<td>#Html.LabelFor(n => n.CourseName)</td>
<td>
#Html.TextBoxFor(n => n.CourseName)
</td>
</tr>
<tr>
<td>#Html.LabelFor(c => c.CourseCredit)</td>
<td>
#Html.TextBoxFor(c => c.CourseCredit)
<br>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" id="Submit" value="Assign" class="btn btn-default" /></td>
</tr>
</table>
</form>
#section scripts
{
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script>
$(document).ready(function() {
$("#departmentId").change(function() {
var dept = $("#departmentId").val();
$("#teacherId").empty();
$("#courseId").empty();
var json = { deptId: dept };
//$("#teacherId").append('<option value="">Select</option>');
$.ajax({
type: "POST",
url: '#Url.Action("GetTeachersByDepartmentId", "TeacherCourseAssign")',
contentType: "application/json; charset=utf-8",
data: JSON.stringify(json),
success: function(data) {
$("#teacherId").append('<option value="">Select</option>');
$.each(data, function(key, value) {
$("#teacherId").append('<option value=' + value.TeacherID + '>' + value.TeacherName + '</option>');
});
}
});
// $("#courseId").append('<option value="">Select</option>');
$.ajax({
type: "POST",
url: '#Url.Action("GetCoursesByDepartmentId", "TeacherCourseAssign")',
contentType: "application/json; charset=utf-8",
data: JSON.stringify(json),
success: function(data) {
$("#courseId").append('<option value="">Select</option>');
$.each(data, function(key, value) {
$("#courseId").append('<option value=' + value.CourseId + '>' + value.CourseCode + '</option>');
});
}
});
});
$("#teacherId").change(function() {
var tech = $("#teacherId").val();
var json = { teacherId: tech };
$.ajax({
type: "POST",
url: '#Url.Action("GetTeachersInfoByTeacherId", "TeacherCourseAssign")',
contentType: "application/json; charset=utf-8",
data: JSON.stringify(json),
success: function(data) {
$.each(data, function(key, value) {
$("#CreditToBeTaken").val(value.CreditToBeTaken);
$("#TeacherRemainingCredit").val(value.CreditToBeTaken);
});
}
});
});
$("#courseId").change(function() {
var tech = $("#courseId").val();
var json = { courseId: tech };
$.ajax({
type: "POST",
url: '#Url.Action("GetCoursesInfoByCourseId", "TeacherCourseAssign")',
contentType: "application/json; charset=utf-8",
data: JSON.stringify(json),
success: function(data) {
$.each(data, function(key, value) {
$("#courseName").val(value.CourseName);
$("#CourseCredit").val(value.Credit);
});
}
});
});
});
</script>
}
My Cascading DropDown for department, course and teacher Info is working fine. but when I click on submit. it is not submitting any value to my post controller SaveTeacherCourseAssign(). want to know am i submitting my model in a wrong way?
Are you able to hit the controller at all? By default, all controllers actions listen to GET requests, so if you can't hit it, you would have to decorate it with [HttpPost] in order to hit it.
Also, I don't see any ajax request that's targeting it. Unless it's the form, at which point you might want to explicitly put an action attribute on it if the page/view name is not the same.
If you're in fact hitting a breakpoint when you submit, are you just getting a null object?
Alright, you have your form element but it doesn't have any action property. You have to add it like:
<form method="POST" id="myForm"
action="#Url.Action("your_action_method_name" , "your_controller_name")" >
I think this is what you are missing.

Send data to controller if item changed

I need to send to controller only those items that was changed by user. For example if first item Jhon changed to Jhon1 it should send, if it changed one more time to 'Jhon' it does not send. How to check this conditions? Use JQuery? For?
#{
ViewBag.Title = "Index";
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/knockout-2.2.0.js"></script>
<h2>Index</h2>
<table>
<thead>
<tr>
<th>Passenger name</th>
</tr>
</thead>
<tbody data-bind="foreach: items">
<tr>
<td><input data-bind="value: name" /></td>
</tr>
</tbody>
</table>
<button data-bind="click: senddata">send</button>
<script>
function MyViewModel() {
var self = this;
self.items = ko.observableArray();
self.items.push({ name: 'Jhon' });
self.items.push({ name: 'Smith' });
self.senddata = function () {
var jsonOfLog = JSON.stringify(self.items());
debugger;
$.ajax({
type: 'POST',
url: 'Home/ConvertLogInfoToXml',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ jsonOfLog: jsonOfLog }),
dataType: 'json'
});
debugger;
}
}
ko.applyBindings(new MyViewModel());
Controller:
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
[HttpPost]
public string ConvertLogInfoToXml(string jsonOfLog)
{
Console.WriteLine(jsonOfLog);
return Convert.ToString(jsonOfLog);
}
}

loading a knockout.js observableArray() from .ajax() call

This puzzles me. It must be something small I'm not seeing. I'm trying to load a very simple observableArray in knockout with an ajax call.
javascript
// we bind the array to the view model property with an empty array.
var data = [];
var viewModel = {
vendors: ko.observableArray(data)
};
ko.applyBindings(viewModel);
$(function () {
// on this click event, we popular the observable array
$('#load').click(function () {
// WORKS. Html is updated appropriately.
viewModel.vendors([{ "Id": "01" },{ "Id": "02" },{ "Id": "03" }]);
// DOES NOT WORK. Fiddler2 shows the same exact json string come back
// as in the example above, and the success function is being called.
$.ajax({
url: '/vendors/10',
dataType: 'json',
success: function (data) {
viewModel.vendors(data);
}
});
});
});
html
<button id="load">Load</button>
<ul data-bind="template: { foreach: vendors }">
<li><span data-bind="text: Id"></span></li>
</ul>
Question: Why does the successful ajax call, who's data variable value matches byte-for-byte the hard typed value, not trigger the html refresh?
There is no reason this would not work fine. As this demonstrates.
http://jsfiddle.net/madcapnmckay/EYueU/
I would check that the ajax post is actually returning json data and that that json is an array and that it's being parsed correctly.
I had to tweak the ajax call to get the fiddle ajax handlers to work correctly.
Nothing more I can think of.
Hope this helps.
var self=this;
//var self first line in model
$.ajax({
url: ",
dataType: "json",
contentType: 'application/json',
type: "POST",
data: JSON.stringify({ }),
processdata: true,
beforeSend: function () {
$.mobile.loading('show');
},
error: function (xhr, textStatus, errorThrown) {
alert('Sorry!');
},
success: function (data) {
$.mobile.loading('hide');
if (data.result!= '') {
self.vendors(data.result);
} else {
self.vendors({something});
}
}
});
Use self.vendors not this viewModel.vendors
Here is what I done in my MVC .net app with knockout and jquery.
// Scripts/groItems.js
(function () {
var ViewModel = function () {
items = ko.observableArray(),
ItemName = ko.observable(),
Img = ko.observable(),
Qty = ko.observable()
}
$.getJSON('/Items2/AllItems', function (data) {
for (var i = 0; i < data.length; i++) {
self.items.push(data[i]);
}
});
var vm = new ViewModel();
$(function () {
ko.applyBindings(vm);
});
}());
#model IEnumerable<GroModel.Item>
#{
ViewBag.Title = "Index";
}
<p>
#Html.ActionLink("Create New", "Create")
</p>
<div data-bind="text: items().length"></div>
<table class="container table table-hover">
<thead>
<tr>
<th>Item name</th>
<th>img</th>
<th>qty</th>
</tr>
</thead>
<tbody data-bind="foreach: items">
<tr>
<td data-bind="text: ItemName"></td>
<td data-bind="text: Img"></td>
<td data-bind="text: Qty"></td>
</tr>
</tbody>
</table>
#section Scripts {
<script src="~/Scripts/knockout-3.4.2.js"></script>
<script src="~/Scripts/groItems.js"></script>
}
Following is part of my code at the Items2Controller.cs
private GroContext db = new GroContext();
public JsonResult AllItems()
{
return Json(db.Items.ToList(), JsonRequestBehavior.AllowGet);
}
Hope this will help. Thanks
We can use a simple JavaScript util function as a work-around.
Instead of viewModel.vendors(data);, wrapping with eval (research the dangers of eval first) will work.
eval("viewModel.vendors("+JSON.stringify(data)+");");
This is bug I think, Knockout's sample is working when we use it with wrapper class:
public class ResultWrapper
{
public Title {get;set;}
public List<Result> {get;set;}
}
http://learn.knockoutjs.com/#/?tutorial=webmail
But if we return Results directly there is no way to bind it. (without extra applyBindings!)

Categories

Resources