i have a table that is "supposed" to be binded with the result of a json:
<table>
<thead>
<tr>
<th>
Id
</th>
<th>
Number
</th>
<th>
Name
</th>
<th>
Password
</th>
<th>
Role
</th>
</tr>
</thead>
<tbody data-bind="foreach: Employees">
<tr>
<td>
<span data-bind="text: EmployeeId"></span>
</td>
<td>
<span data-bind="text: EmployeeNumber"></span>
</td>
<td>
<span data-bind="text: EmployeeName"></span>
</td>
<td>
<span data-bind="text: EmployeePassword"></span>
</td>
<td>
<span data-bind="text: EmployeeRole"></span>
</td>
</tr>
</tbody>
my knockout script for that is this:
<script type="text/javascript">
$(document).ready(function () {
var viewModel = {};
var data = $.getJSON("Employees.json", function (data) {
viewModel.model = ko.mapping.fromJSON(data);
ko.applyBindings(viewModel);
}
);
});
</script>
i am trying to bind the table with the json result but it is not working, where could be the problem... here is my json in controller:
public ActionResult GetEmployees()
{
var r = db.Employees;
var s = new
{
Employees = r.Select(x => new { empId = x.Id, empName = x.Name, empNumber = x.Number, empPassword = x.Password, empRole = x.Role }).ToList()
.Select(x => new
{
EmployeeId = x.empId,
EmployeeName = x.empName,
EmployeeNumber = x.empNumber,
EmployeePassword = x.empPassword,
EmployeeRole = x.empRole
}).ToArray(),
};
return Json(s, JsonRequestBehavior.AllowGet);
}
UPDATE: here is my sample returned json data:
{"Employees":[{"EmployeeId":1,"EmployeeName":X","EmployeeNumber":"1","EmployeePassword":"x","EmployeeRole":"User"},{"EmployeeId":10,"EmployeeName":"S","EmployeeNumber":"21","EmployeePassword":"s","EmployeeRole":"Admin"}]}
Assuming everything server side is fine, your model is being bound to a .model property but so your foreach should be
<tbody data-bind="foreach: model.Employees">
That's all I can see right now, will need to see more code to help further.
You may want to use firebug or chrome dev tools and confirm what javascript errors you are receiving if any, also check the response to make sure your action method is returning data.
EDIT
OK here is a jsfiddle of your code. A few things, probably typos but just in case. Missing tag in your markup and there is a un-terminated comment in your json before the first EmployeeName.
http://jsfiddle.net/madcapnmckay/3rRUQ/1/
You do need to the model.Employees as stated above. Because you are returning json from mvc it will have the correct headers so jquery will convert it to a javascript object automatically so no need for the fromJSON, instead try fromJS.
Hope this helps.
<script id="tmpl_ScreenNavigation" type="text/html">
<tr class="erow">
{{if ScreenParentNevigationId}}
<td width="250px"><table cellpadding="5" class="Permission" sceenid="${ScreenNevigationId}" border="0" RoleDetailId="0"><tr><td><label><input type="checkbox" id="view${ScreenNevigationId}" class="View" /> View</label></td><td><label><input type="checkbox" id="AddModify${ScreenNevigationId}" class="Save"/> Add/Modify</label></td><td><label><input type="checkbox" id="Delete${ScreenNevigationId}" class="Delete" /> Delete</label></td></tr></table></td>
{{/if}}
{{if !ScreenParentNevigationId}}
<td {{if !ScreenParentNevigationId}} style="background-color: #F9BDC8;"{{/if}} width="250px"><table cellpadding="5" class="Permission" sceenid="${ScreenNevigationId}" border="0" RoleDetailId="0"><tr><td {{if !ScreenParentNevigationId}} style="background-color: #F9BDC8;"{{/if}}><label><input type="checkbox" id="view${ScreenNevigationId}" class="View" /> View</label></td></tr></table></td>
{{/if}}
<td {{if !ScreenParentNevigationId}} style="background-color: #F9BDC8;"{{/if}}>${ScreenName}</td>
<td {{if !ScreenParentNevigationId}} style="background-color: #F9BDC8;"{{/if}}>${ScreenDescription}</td>
</tr>
</script>
$("#tmpl_ScreenNavigation").tmpl(resultJson).appendTo("#tblRoles");
Change the location of your JavaScript tag to the top of the html file just above the table. The data might not be populating correctly because of that.
Related
I have a project with Spring Mvc and I want to use Bootstrap modal windows and Thymeleaf. I hava a view students.jsp witch get list of students from model when I make loop without Thymeleaf everything work ok.
I use JS. But when I use Thymeleaf model windows didn't work ok.
<table class="table table-hover">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
<th></th>
</tr>
</thead>
<tbody>
<tr id="user-${user.id}" th:each="user: ${students}">
<td th:text="${user.id}" />
<td th:text="${user.firstName}" />
<td th:text="${user.lastName}" />
<td>
<button type="button" class="btn btn-primary editButton"
data-toggle="modal" data-target="#myModal" data-user-id="${user.id}">Edit</button>
</td>
</tr>
</tbody>
</table>
<script type="text/javascript">
$("#myModal").on('show.bs.modal', function(e) {
var userId = $(e.relatedTarget).data('user-id');
var cols = $('#user-' + userId + ' td');
var firstName = $(cols[0]).text();
var lastName = $(cols[1]).text();
var email = $(cols[2]).text();
$('#firstNameInput').val(firstName);
$('#lastNameInput').val(lastName);
$('#emailInput').val(email);
});
$("#myModal").on('hidden.bs.modal', function() {
var form = $(this).find('form');
form[0].reset();
});
</script>
It doesn't get data from list. I don't know how to solve this problem. Please help me :)
There's a small problem with data-user-id attribute in your "Edit" button.
Instead of:
data-user-id="${user.id}"
...you should have:
th:data-user-id="${user.id}"
...so that the attribute is processed by Thymeleaf and ${user.id} actually replaced with expected value.
<tr th:each="user: ${students}" th:id="'user-' + ${user.id}">
<td th:text="${user.id}" />
<td th:text="${user.firstName}" />
<td th:text="${user.lastName}" />
<td th:text="${user.email}" />
<td>
<button type="button" class="btn btn-primary editButton"
data-toggle="modal" data-target="#myModal"
th:data-user-id="${user.id}">Edit</button>
</td>
</tr>
I want to inquire about the way I can get more results when I click on a "show more" button, without loading the page and without repeating the same results.
For example, I have a result set from the database and suppose it has 10 results. Under them I have a button named "show more". When I click on it I'll see another 10 results, and so on.
Also here is an image:
My view:
#model SmartBookLibrary.ViewModel.UserVm
<table class="table table-striped table-bordered table-advance table-hover">
<thead>
<tr>
<th>
<i class="fa fa-image"></i> Image
</th>
<th class="hidden-xs">
<i class="fa fa-book"></i> Book Name
</th>
<th class="hidden-xs">
<i class="fa fa-eye"></i> Views
</th>
<th> </th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.ReadLaters)
{
<tr>
<td>
<img class="img-thumbnail circle" src="~/Images/#item.Book.Book_Image" style="width:75px;height:75px" />
</td>
<td class="hidden-xs">
<h4><b>#item.Book.Book_name</b></h4>
</td>
<td>
700
<span class="label label-success label-sm"> Views </span>
</td>
<td>
<a class="btn btn-sm grey-salsa btn-outline" href="~/book/#item.Book_Id/#item.Book.UrlSlug"> View </a>
</td>
</tr>
}
</tbody>
</table>
<input type="submit" class="btn green-sharp btn-outline btn-block sbold uppercase" value="Load More">
My controller method:
[HttpGet]
public ActionResult Index()
{
//Get current user id to check
var x = User.Identity.GetUserId();
var vm = new UserVm();
//ReadLater Books
var ReadLaterBooks = db.ReadLaters.Where(p => p.User_Id == x).ToList();
var ReadLaterBooksResult = ReadLaterBooks.Take(5).ToList();
if (ReadLaterBooks != null)
{
vm.ReadLaters = ReadLaterBooksResult;
}
return View(vm);
}
So, how can I make that work using ajax or whatever? Thanks!
I'm creating Advanced Search using MVC. What I mean by Advanced Search is user can do combination search, for example, user can search by category = 'Child' and name contains 'A' or age <= 10. then the result is displayed using MVC PagedList.
I followed UnobtrusiveAjax tutorial based on example from PagedList source. I defined 2 files, Index.cshtml for View and _List.cshtml for PartialView. Index contains search criteria and a button to add more clause.
and _List contains table for displaying the result using AJAX
The problem is after I filtered by code for example contains 'A' and click search then navigate to page 2 the filter value is missing and it will display code which not contains 'A'. How to solve this problem?
ViewModel:
public class WorkflowStateListViewModel
{
public IEnumerable<string> FilterField { get; set; }
public IEnumerable<string> FilterOperator { get; set; }
public IEnumerable<string> FilterString { get; set; }
public IEnumerable<string> FilterLogical { get; set; }
public PagedList<WorkflowStateListDetailViewModel> WorkflowStateListDetailVM { get; set; }
public int? Page { get; set; }
}
Controller:
public ActionResult Filter(WorkflowStateListViewModel workflowStateListVM, int? page)
{
var workflowStatesQuery = from ws in db.WorkflowStates
where ws.RowStatus == true
select ws;
if (workflowStateListVM.FilterField != null)
{
for (int i = 0; i < workflowStateListVM.FilterField.Count(); i++)
{
workflowStatesQuery = DoFilter(workflowStatesQuery, workflowStateListVM.FilterField.ElementAt(i), workflowStateListVM.FilterOperator.ElementAt(i), workflowStateListVM.FilterString.ElementAt(i));
}
}
workflowStatesQuery = workflowStatesQuery.OrderBy(ws => ws.Code);
var workflowStateListDetailVM = from ws in workflowStatesQuery
select new WorkflowStateListDetailViewModel()
{
WorkflowStateID = ws.WorkflowStateID,
Code = ws.Code,
Name = ws.Name,
Level = ws.Level,
PIC = ws.PIC
};
int pageNumber = (page ?? 1);
return PartialView("_List", workflowStateListDetailVM.ToPagedList(pageNumber, 5));
}
Index.cshtml
#model ViewModels.WorkflowStateListViewModel
#using (Ajax.BeginForm("Filter", "WorkflowState",
new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET",
UpdateTargetId = "workflowStateList"
},
new { #class = "form-inline" }))
{
<div id="clauses">
</div>
<p>
<div class="form-group">
#Html.DropDownList("FilterField", new SelectList(Model.FilterField), new { #class = "form-control" })
</div>
<div class="form-group">
#Html.DropDownList("FilterOperator", new SelectList(Model.FilterOperator), new { #class = "form-control" })
</div>
<div class="form-group">
#Html.TextBoxFor(model => model.FilterString, new { #class = "form-control" })
</div>
<input type="submit" value="Search" class="btn btn-default" />
</p>
<p>
<div class="form-group">
<span class="glyphicon glyphicon-plus-sign"></span> Add new clause
</div>
</p>
<div id="workflowStateList">
#{ Html.RenderPartial("_List", Model); }
</div>
}
_List.cshtml
#model JOeBilling.ViewModels.WorkflowStateListViewModel
#using PagedList.Mvc;
<div class="table-responsive">
<table class="table table-striped table-hover table-condensed">
<tr>
<th></th>
<th>
Code
</th>
<th>
Name
</th>
<th>
Level
</th>
<th>
PIC
</th>
</tr>
#foreach (var item in Model.WorkflowStateListDetailVM)
{
<tr>
<td>
<span class="glyphicon glyphicon-pencil"></span>
<span class="glyphicon glyphicon-eye-open"></span>
<span class="glyphicon glyphicon-remove"></span>
</td>
<td>
#Html.DisplayFor(modelItem => item.Code)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Level)
</td>
<td>
#Html.DisplayFor(modelItem => item.PIC)
</td>
</tr>
}
</table>
</div>
<br />
Page #(Model.WorkflowStateListDetailVM.PageCount < Model.WorkflowStateListDetailVM.PageNumber ? 0 : Model.WorkflowStateListDetailVM.PageNumber) of #Model.WorkflowStateListDetailVM.PageCount
#Html.PagedListPager(Model.WorkflowStateListDetailVM,
page => Url.Action("Filter", new { page }),
PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(new AjaxOptions() { HttpMethod = "GET", UpdateTargetId = "workflowStateList" }))
UPDATE
UPDATE 2
UPDATE 3 Response tab
<link href="/Content/PagedList.css" rel="stylesheet" type="text/css" />
<div class="table-responsive">
<table class="table table-striped table-hover table-condensed">
<tr>
<th></th>
<th>
Code
</th>
<th>
Name
</th>
<th>
Level
</th>
<th>
PIC
</th>
<th>
Created By
</th>
<th>
Created Date
</th>
<th>
Modified By
</th>
<th>
Modified Date
</th>
</tr>
<tr>
<td>
<span class="glyphicon glyphicon-pencil"></span>
<span class="glyphicon glyphicon-eye-open"></span>
<span class="glyphicon glyphicon-remove"></span>
</td>
<td>
A06
</td>
<td>
Preparing Task Code
</td>
<td>
6
</td>
<td>
</td>
<td>
JKTWLA
</td>
<td>
28/04/2014 4:24:52 PM
</td>
<td>
</td>
<td>
</td>
</tr>
<tr>
<td>
<span class="glyphicon glyphicon-pencil"></span>
<span class="glyphicon glyphicon-eye-open"></span>
<span class="glyphicon glyphicon-remove"></span>
</td>
<td>
A07
</td>
<td>
Closed
</td>
<td>
7
</td>
<td>
</td>
<td>
JKTWLA
</td>
<td>
28/04/2014 4:25:06 PM
</td>
<td>
</td>
<td>
</td>
</tr>
<tr>
<td>
<span class="glyphicon glyphicon-pencil"></span>
<span class="glyphicon glyphicon-eye-open"></span>
<span class="glyphicon glyphicon-remove"></span>
</td>
<td>
C01
</td>
<td>
New Invoice
</td>
<td>
1
</td>
<td>
</td>
<td>
JKTWLA
</td>
<td>
13/06/2014 10:49:00 AM
</td>
<td>
</td>
<td>
</td>
</tr>
</table>
</div>
<br />
Page 2 of 2
<div class="pagination-container"><ul class="pagination"><li class="PagedList-skipToPrevious"><a data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#workflowStateList" href="/WorkflowState/Filter?page=1" rel="prev">«</a></li><li><a data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#workflowStateList" href="/WorkflowState/Filter?page=1">1</a></li><li class="active"><a>2</a></li></ul></div>
I have table with datas from database (insert dynamically). In one column I insert checkbox. Now I want to select one of them and send to next form (I select one product and send properties to another form. In this form should be displayed properties only the select product). But I don't know what kind of value insert in th:field="*{}". I tried many solutions but doesn't work. My html form with all products table:
<form action="/oferta/zamow" th:action="#{/oferta/zamow}"
th:object="${oferta}" method="post">
<table border="1" id="display-data">
<tr>
<td>#</td>
<td>title</td>
<td>author</td>
<td>rok</td>
<td>cena</td>
<td></td>
</tr>
<tr th:each="produkt, pozycja : ${oferta}">
<td th:text="${pozycja.count}"></td>
<td><span th:text="${produkt.tytul}"></span></td>
<td><span th:text="${produkt.autor}"></span></td>
<td><span th:text="${produkt.rok}"></span></td>
<td><span th:text="${produkt.cena}"></span></td>
<td>
<input type="submit" value="zamow"/>
<!-- <a th:href="#{/zamowienie}">zamow</a> -->
</td>
<td>
<label>zamow</label>
<input type="checkbox" th:field="*{produkt}" th:value="${produkt}"/>
</td>
</tr>
</table>
</form>
Form to display select product:
<form action="/zamowienie/zam" th:action="#{/zamowienie/zam}"
th:object="${zamowienie}" method="post">
<table border="1" id="display-data">
<tr align="center">
<td colspan="2">twoje zamowienie</td>
</tr>
<tr>
<td>tytul</td>
<td><span th:text="${produkt.tytul}"></span></td>
</tr>
<tr>
<td>autor</td>
<td><span th:text="${produkt.autor}"></span></td>
</tr>
<tr>
<td>rok</td>
<td><span th:text="${produkt.rok}"></span></td>
</tr>
<tr>
<td>cena</td>
<td><span th:text="${produkt.cena}"></span></td>
</tr>
<tr>
<td>data zlozenia zamowienia</td>
<td><span th:text="${datazam}"></span></td>
</tr>
</table>
</form>
Thanks for help.
I am not sure if this is the answer you seek, but you can find an example at http://www.thymeleaf.org/doc/html/Thymeleaf-Spring3.html#checkbox-fields.
Here is a simple example to illustrate how to use a checkbox in Thymeleaf with Spring MVC.
Controller:
#RequestMapping(value = "/showForm", method=RequestMethod.GET)
public String showForm(Model model) {
List<String> allItems = new ArrayList<String>();
allItems.add("value1");
allItems.add("value2");
allItems.add("value3");
model.addAttribute("allItems", allItems);
Foo foo = new Foo();
List<String> checkedItems = new ArrayList<String>();
// value1 will be checked by default.
checkedItems.add("value1");
foo.setCheckedItems(checkedItems);
model.addAttribute("foo", foo);
...
}
#RequestMapping(value = "/processForm", method=RequestMethod.POST)
public String processForm(#ModelAttribute(value="foo") Foo foo) {
// Get value of checked item.
List<String> checkedItems = foo.getCheckedItems();
...
}
html:
<form action="#" th:action="#{/processForm}" th:object="${foo}" method="post">
<div th:each="item : ${allItems}">
<input type="checkbox" th:field="*{checkedItems}" th:value="${item}" />
<label th:text="${item}">example</label>
</div>
<input type="submit" />
</form>
Foo.java:
public class Foo {
private List<String> checkedItems;
public List<String> getCheckedItems() {
return checkedItems;
}
public void setCheckedItems(List<String> checkedItems) {
this.checkedItems = checkedItems;
}
}
Hope this helps.
Take a look at the thymeleaf spring integration docs.
All th:field are mapped against the command object. Thats why you need the *{} expression.
One thing the template engine is not able to do (yet) is mapping fields inside a loop directly. So you cannot use the *{} approach to reference the produkt variable from the loop.
What you have to do is use the index of the th:each expression and build a property accessor with a pre-evaluated expression for the index.
<input type="checkbox" th:field="*{produkts[__${index}__].checked" />
You do not need the th:value, th:field is taking care of it. (Except if you want to superseed it)
i have the following view:-
<script type="text/javascript">
$(document).ready(function () {
$("#removerow").click(function () {
$(this).remove();
});
});
</script>
<h2>Details</h2>
<fieldset>
<legend>This Question Currently has #Model.Answers.Count() Answers/s. </legend>
<table id="incrementanswer">
<tr>
<th>
Description
</th>
<th>
Answer
</th>
<th></th>
</tr>
#foreach (var answer in Model.Answers.OrderBy(a=> a.IsRight))
{
<tr id = "removerow">
<td>
#Html.DisplayFor(modelItem => answer.Description)
</td>
<td>
#Html.DisplayFor(modelItem => answer.Answer_Description.description)
</td>
<td>
#Ajax.ActionLink("Delete", "Delete", "Answer",
new { id = answer.AnswersID },
new AjaxOptions
{
Confirm = "Are You sure You want to delete this Answer ?",
HttpMethod = "Post",
UpdateTargetId = "toremove",
OnSuccess = "removePartial2"
})
</td>
</tr>
}
</table>
<div id = "progress2">
<img src= "#Url.Content("~/Content/images/ajax-loader1.gif") ">
</div>
which contains a script and an ajax.actionlink that calls this script after clicking on the delete link. Currently the row will be removed only if it is the first row in a table and also the row will be deleted before confirming the deletion ,, so what might be the problem ?
edited:- i have updated my view to the following, but i still can not force the removePartial2 script to remove the row which was deleted:-
</script>
<script type="text/javascript">
function removePartial2() {
$(this).remove();
}
</script>
}
<h2>Details</h2>
<fieldset>
<legend>This Question Currently has #Model.Answers.Count() Answers/s. </legend>
<table id="incrementanswer">
<tr>
<th>
Description
</th>
<th>
Answer
</th>
<th></th>
</tr>
#foreach (var answer in Model.Answers.OrderBy(a=> a.IsRight))
{
<tr id = #answer.AnswersID>
<td>
#Html.DisplayFor(modelItem => answer.Description)
</td>
<td>
#Html.DisplayFor(modelItem => answer.Answer_Description.description)
</td>
<td>
#Ajax.ActionLink("Delete", "Delete", "Answer",
new { id = answer.AnswersID },
new AjaxOptions
{
Confirm = "Are You sure You want to delete this Answer ?",
HttpMethod = "Post",
UpdateTargetId = #answer.AnswersID.ToString(),
OnSuccess = "removePartial2"
})
</td>
</tr>
}
</table>
<div id = "progress2">
<img src= "#Url.Content("~/Content/images/ajax-loader1.gif") ">
</div>
"Ids. Must. Be. Unique."
You have a function that removes the row if the ROW is clicked, not just the delete option. I would remove your first javascript block, and only use the ajax call function.
OnSuccess is whether or not the Ajax call returned a 200 code. This is only if the ajax call was successful - It's not checking to see if a returned value was correct.