Datatable view is not in style/standard format - ajax

I am trying to figure out what I've missed during my coding on my project. My problem is my datatable format/style is not what it seems to look like from standard format. I'm using ASP.net MVC.
This is the output: Page numbers, search box is not in style
Page numbers, search box is not in style
Here is my code:
<div class="row">
<div class="col-sm-20c">
<div class="panel-body">
<table id="tbl-transaction" class="table table-bordered" cellspacing="0" width="100%" align="center">
<thead>
<tr>
<th>Transaction No</th>
<th>Purpose of Visit</th>
<th>Name of Host</th>
<th>Transacted By</th>
<th>Details</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
#section Scripts
{
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.dataTables.min.js"></script>
<script>
getall();
function getall()
{
$('#tbl-transaction').dataTable().fnDestroy();
$('#tbl-transaction').DataTable({
"ajax": {
"url": '/FSEWeb/Admin/GetAllTransactions',
"type": "get",
"datatype" : "JSON"
},
"columns" :
[
{ data :"TransactionNumber"},
{ data: "PurposeOfVisit" },
{ data: "NameOfHostFromST" },
{ data: "TransactedBy" },
{
data: null, "render" : function(data,type,row)
{
return '<button class= "btn btn-success" onclick = "get_details(' + data.id + ',' + data.TransactionNumber + ')"> Details </button>';
}
}
]
})
}
This table format is what I want to look like.
Desired output with styles

You have not incorporated JQuery Datatbles style sheet i.e.
<!-- Data table -->
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.10/css/dataTables.bootstrap.min.css " />
Incorporate it at layout level or page level.

Related

Grails, sorting and filtering a grid at the same time using ajax

I have a grid(html-table) with a lot of columns and want to combine filtering and sorting on this table.
At the moment I only use filtering on one column but sorting on several columns.
I want to do this with ajax.
I read an article [http://www.craigburke.com/2011/01/23/grails-ajax-list-with-paging-sorting-and-filtering.html]
and tried to adapt it to my version of grails-3.2.6.
This has been very hard to solve and now I'm totally stuck.
If I add something in the filter nothing happens but when I click on a column, the filtering takes place and also sorting, clicking a second time, ajax is not called and the filter is overwritten with the default value. I have managed to implement it on a test project which act the same.
It is much code and maybe there is a way to include the whole project in this question in some way?
I'll try to show most of the important part here if it could help.
The index.gsp:
<!DOCTYPE html>
<html>
<head>
<meta name="layout" content="main" />
<g:set var="entityName" value="${message(code: 'person.label', default: 'Person')}" />
<title><g:message code="default.list.label" args="[entityName]" /></title>
<script type="text/javascript">
$(document).ready(function() {
setupGridAjax();
setupFilterAjax();
});
</script>
<script type="text/javascript">
function setupGridAjax() {
$('#gridPersons').find('.paginateButtons a, th.sortable a').on('click', function(event) {
event.preventDefault();
var url = $(this).attr('href');
var grid = $(this).parents("table.ajax");
$(grid).html($("#spinner").html());
$.ajax({
type: 'GET',
url: url,
data: [tag],
success: function(data) {
$(grid).fadeOut('fast', function() {$(this).html(data).fadeIn('slow');});
}
})
});
}
</script>
<script type="text/javascript">
// Turn any input changes or form submission within a filter div into an ajax call
function setupFilterAjax(){
alert('FILTER--Anropat');
$('div.filters select:input').on('change',function(event) {
var filterBox = $(this).parents("div.filters");
filterGrid(filterBox);
});
$("div.filters form").submit(function() {
var filterBox = $(this).parents("div.filters");
alert('FILTERBOX - '+filterBox);
filterGrid(filterBox);
return false;
});
}
// Reload grid based on selections from the filter
function filterGrid(filterBox) {
alert('FILTER-change detected');
var grid = $(filterBox).next("div.gridPersons");
$(grid).html($("#spinner").html());
var form = $(filterBox).find("form");
var url = $(form).attr("action");
var data = $(form).serialize();
alert('FILTERGRID - '+url);
$.ajax({
type: 'POST',
url: '${g.createLink( controller:'person', action:'index' )}',
data: [tag],
success: function(data) {
$(grid).fadeOut('fast', function() {$(this).html(data).fadeIn('slow');});
}
});
}
</script>
</head>
<body>
<g:message code="default.link.skip.label" default="Skip to content…"/>
<div class="nav" role="navigation">
<ul>
<li><a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a></li>
<li><g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></li>
</ul>
</div>
<div id="list-person" class="content scaffold-list" role="main">
<h1><g:message code="default.list.label" args="[entityName]" /></h1>
<g:if test="${flash.message}">
<div class="message" role="status">${flash.message}</div>
</g:if>
<div class="filters">
<g:form action="register">
<div id="selectMill">
Select tags:
<g:select class="selected" name="tag" from="${tagList}" value="${filters?.tag}" noSelection = "${['':'All']}" optionValue="" optionKey="" />
</div>
<div id="gridPersons">
<g:render template="Grid_Persons" model="personList" />
</div>
<div class="pagination">
<g:paginate total="${personCount ?: 0}" />
</div>
<fieldset class="buttons">
<input class="save" type="submit" value="${message(code: 'offer.create.from.buffer.label', default: 'Create')}" />
</fieldset>
</g:form>
</div>
</div>
</body>
The template: _Grid_Persons.gsp
<table class="ajax">
<thead>
<tr>
<g:sortableColumn property='reg' title='Register' />
<g:sortableColumn property="id" title='Id' params="${filters}"/>
<g:sortableColumn property='name' title='Name' params="${filters}"/>
<g:sortableColumn property='tag' title='Tag' params="${filters}"/>
<g:sortableColumn property='registered' title='Registered' params="${filters}"/>
</thead>
<tbody>
<g:each in="${personList}" status="i" var="ps">
<tr class="${ (i % 2) == 0 ? 'even': 'odd'}">
<td><g:checkBox name="ckb" value="${ps.id}" checked="false" /></td>
<td><g:link action="edit" id="${ps.id}">${ps.id}</g:link></td>
<td>${ps.name}</td>
<td>${ps.tag}</td>
<td>${ps.registered}</td>
<td>
</g:each>
</tbody>
The index-part of the controller:
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
def tagList = Person.withCriteria {
projections {
distinct("tag")
}
}
def List<Person> personList = getPersonList()
// Paging def prodBuffer = getPaginatedList(prodBuffer, max, params.offset?.toInteger())
def filters = [tag: params.tag, sort: params.sort, order: params.order]
def model = [personList: personList, filters:filters, tagList:tagList]
if (request.xhr) {
println("AJAX-Request!!!")
render(template:"Grid_Persons", model:model)
prodBuffer, offerDetails:offerDetails, filters:filters])
} else {
offerDetails: offerDetails, millList: millList, selectedMill:false, prodBufferCount: ProdBuffer.count()]
[personList:personList,tagList:tagList]
}
Person.count(), tagList:tagList]
}
def List<Person> getPersonList() {
println("getPersonList tag: "+params.tag)
def tag = params.tag
def c = Person.createCriteria()
def tempList = c.list {
if (tag) eq("tag", tag)
if (params.sort){
order(params.sort, params.order)
}
}
return tempList
}
From debugging:
The page is loaded:
getPersonList tag: null
Selected "Grails" in the filter:
getPersonList tag: Grails
AJAX-Request!!!
Klicked on the "Name"-column header
getPersonList tag: Grails
AJAX-Request!!!
-- Now the list is sorted(ascending) and filtered
Klicked on the column again:
getPersonList tag: Grails
-- Now the list is resorted(descending) and the filtering still ok but the SELECT TAGS now view "All"
Klicked the column for the third time:
getPersonList tag:
AJAX-Request!!!
-- Now the list show all lines and resorted(ascending)
Now solved by using the recommended plugin - datatables.
In case you are in a hurry you can inject https://datatables.net/ that adds the utilities you require among others

How to convert html <table> to Handsontable which table has html input fields also

I want to show a dynamic table which has records coming from a custom search.
Now I want to make the table row as an inline editable row.
I also need pagination with the table since I have 30 to 40 table columns which I need to display on the same table (scroll for columns).
I used Handsontable to achieve this as seen below, however, the image is not coming as I have entered in the table cell.
<!doctype html>
<html>
<head>
<meta charset='utf-8'>
<title>Scroll - Handsontable</title>
<script data-jsfiddle="common" src="handsontable.full.js"></script>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<link data-jsfiddle="common" rel="stylesheet" media="screen" href="handsontable.full.css">
</head>
<body>
<div id="example1" style="width: 700px; height: 400px; overflow: auto">
<table id="example" class="row-border hover order-column" cellspacing="0" style="Display: none;" >
<thead>
<tr>
<th>Action</th>
<th>ID</th>
<th>Name</th>
<th>Address</th>
</tr>
</thead>
<tbody>
<tr>
<td><img src="edit.jpg" height="20" width="20"/></td>
<td>1</td>
<td>test</td>
<td>test</td>
</tr>
<tr>
<td><img src="edit.jpg" height="20" width="20"/></td>
<td>2</td>
<td>test2</td>
<td>test2</td>
</tr>
<tr>
<td><img src="edit.jpg" height="20" width="20"/></td>
<td>3</td>
<td>test3</td>
<td>test3</td>
</tr>
</tbody>
</table>
</div>
<script data-jsfiddle="example1">
var data=$('#example tr').map(function(tr){
return [$(this).children().map(function(td){return $(this).text()}).get()]
}).get()
var
example = document.getElementById('example1'),
maximize = document.querySelector('.maximize'),
maxed = false,
resizeTimeout,
availableWidth,
availableHeight,
hot1;
hot1 = new Handsontable(example,{
data: data,
// colWidths: [55, 80, 80, 80, 80, 80, 80], //can also be a number or a function
rowHeaders: false,
colHeaders: false,
fixedColumnsLeft: 2,
fixedRowsTop: 1,
minSpareRows: 1,
contextMenu: true
});
function calculateSize() {
var offset;
if (maxed) {
offset = Handsontable.Dom.offset(example);
availableWidth = Handsontable.Dom.innerWidth(document.body) - offset.left + window.scrollX;
availableHeight = Handsontable.Dom.innerHeight(document.body) - offset.top + window.scrollY;
example.style.width = availableWidth + 'px';
example.style.height = availableHeight + 'px';
}
}
</script>
</div>
</body>
</html>
From the looks of it, your definition of the Handsontable is correct. Are you pasting that HTML after it's rendered or is that what Handsontable is creating for you? I'm not sure if you knew or not but you don't need to define the table in the HTML for this to work. As a matter of fact you should NOT be defining it.
If this was just the rendered code, could you please elaborate on what you mean by "I have used Handsontable for achieve this as below. but image not coming as i have entered in table cell."? What parts are wrong and what do you need changed?
Try this:
cells : function (row, col, prop) { return { renderer: 'html' }; }
as an option in your hot1 definition.

Knockout observableArray not binding

I am trying to bind an observableArray from an ajax server read but not able to bind it to the html. The json data is returning but not sure how to parse or get it to bind. I am new to Knockout.
Code:
<html>
<head>
<title></title>
<script type='text/javascript' src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script>
<script type='text/javascript' src="http://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.3.5/knockout.mapping.js"></script>
<script type='text/javascript' src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.js"></script>
<script>
function SurnameViewModel() {
var self = this;
self.Surnames = ko.observableArray();
$.ajax({
crossDomain: true,
type: 'POST',
url: "http://localhost/GetSurnames/Name/CID",
dataType: 'json',
data: { "Name": "d", "CID": "17" }, // <==this is just a sample data
processdata: true,
success: function (result) {
self.Surnames= ko.mapping.fromJS(result.data);
alert(self.Surnames()); // <== able to see the json data
},
error: function (xhr, ajaxOptions, thrownError) {
alert("Failure!");
alert(xhr.status);
alert(thrownError);
}
});
}
// Activates knockout.js
$(document).ready(function() {
ko.applyBindings(new SurnameViewModel())
});
</script>
</head>
<body>
<h2>Surnames</h2>
<table>
<thead><tr>
<th>ID</th><th>Surname</th>
</tr></thead>
<tbody data-bind="foreach: Surnames">
<tr>
<td data-bind="text: Surnames().id"></td>
<td data-bind="text: Surnames().homename"></td>
</tr>
</tbody>
</table>
</body>
</html>
Json Data Returned from the alert
data: "[{"id":3,"homename":"DCosta"}]"
What am doing wrong here?
Edit: Working code
This is what worked for me.
I change this
ko.mapping.fromJS(result.data, {}, self.Surnames);
to
ko.mapping.fromJSON(result.data, {}, self.Surnames);
and in the html from this
<tr>
<td data-bind="text: Surnames().id"></td>
<td data-bind="text: Surnames().homename"></td>
</tr>
to this
<tr>
<td data-bind="text: id"></td>
<td data-bind="text: homename"></td>
</tr>
You have two problems:
In your view when using the foreach binding you are "inside" of the context of the array so you don't need to write out the array name (Surnames()) again:
<tbody data-bind="foreach: Surnames">
<tr>
<td data-bind="text: id"></td>
<td data-bind="text: homename"></td>
</tr>
</tbody>
When you are getting back the data from the server you are overriding the Surnames array, the correct way of using the mapping plugin here:
ko.mapping.fromJS(result.data, {} /* empty mapping options */, self.Surnames);
Or
self.Surnames(ko.mapping.fromJS(result.data)());
Note the () in the above code, you need this because the ko.mapping.fromJS(result.data) will return an ko.observableArray without getting its underlaying value with the () you would end up with your Surnames containing another ko.observableArray

Using a partial view to represent a table row

I am trying to use a partial view to represent rows of a table in my project. I currently have
<table>
<thead>
<tr>
<th >
Column 1
</th>
<th >
Column 2
</th>
<th >
Column 3
</th>
</tr>
</thead>
<tbody>
#foreach(var item in Model.Items)
{
#Html.Action("ItemCalculatedView", new { Id = item.Id})
}
</tbody>
</table>
In my partial view I have this
#using (Ajax.BeginForm("SaveStuff", "Whatever",
new { id = #Model.Id }, new AjaxOptions()
{
HttpMethod = "Post",
OnSuccess = "Success"
}))
{
#Html.HiddenFor(m => m.Id)
<tr>
<td>
#Html.Label("Col1", Model.Col1)
</td>
<td>
#Html.TextBox("Number", Model.Number)
</td>
<td>
<input type="submit" id='submit-#Model.Id'/>
</td>
</tr>
}
How can I make this work?
You can put a form inside a table cell, but you can't have the form inside a tbody element, or spanning multiple columns. So there are three options:
Use a CSS layout instead of a table, or use divs with CSS display set to "table". (for example)
Put the entire form (TextBox and Submit) inside a td
Put another table inside the td element
I'd recommend #1 -- use a CSS layout to construct the table, since it's difficult to style table tags:
Main
<div class="table">
<div class="header-row">
<div class="header-cell">Column 1</th>
<div class="header-cell">Column 2</th>
<div class="header-cell">Column 3</th>
</div>
#foreach(var item in Model.Items)
{
#Html.Action("ItemCalculatedView", new { Id = item.Id})
}
</div>
Partial
#using (Ajax.BeginForm(
actionName: "SaveStuff",
controllerName: "Whatever",
routeValues: new { id = #Model.Id },
ajaxOptions: new AjaxOptions
{
HttpMethod = "Post",
OnSuccess = "Success"
},
htmlAttributes: new { #class = "row" }
))
{
<div class="cell">
#Html.HiddenFor(m => m.Id)
</div>
<div class="cell">
#Html.Label("Col1", Model.Col1)
</div>
<div class="cell">
#Html.TextBox("Number", Model.Number)
</div>
<div class="cell">
<input type="submit" id='submit-#Model.Id'/>
</div>
}
CSS
.table { display: table; }
.header-row, row { display: table-row; }
.header-cell, cell { display: table-cell; }
You have several issues here. First, as dbaseman mentions, you can't place forms within the structure of a table and have it be legal HTML. It may work, or it might not, and even if it does work, you can't guarantee it will continue to work.
I would instead wrap your table in the form, and then on the post figure out which button was pressed based on its value and/or index.
I would strongly advise against using css tables for tabular data. It's just not semantically correct.
Another possible solution is, instead of using the Ajax.BeginForm, instead use jQuery $.ajax and then you can select a row of data in javascript to post to the server.

jquery error this.source is not a function

Hi I am trying to catch an array of string from a class called AjaxFacade using DWR and I am using jquery to autocomplete a text box snippetof my jsp code is as follows
<%
String path = request.getContextPath();
%>
<script type='text/javascript' src='<%=path%>/dwr/interface/ajaxFacade.js'></script>
<script type='text/javascript' src='<%=path%>/dwr/engine.js'></script>
<script type='text/javascript' src='<%=path%>/dwr/util.js'></script>
<script>
$(function()
{
var countries ;
countries = ajaxFacade.getCountries();
$("#tags").autocomplete({source : countries});
});
</script>
<tr>
<td align="left" valign="top" bgcolor="e3ddc7">
<div align="right"><strong> <font color="red">*</font>Old E-mail Address:</strong></div>
</td>
<td align="left" valign="top" bgcolor="#FFFFFF">
<html:text name="amsUserRequestForm" property="oldEmail" size="20" styleClass="ui-widget" styleId="tags">
</html:text></td>
</tr>
Function in AjaxFacade class is as follows
public String[] getUsers() {
String[] countries = {
"India",
"Iran",
"Iraq",
"Indoneshia",
"Ireland"
};
return countries;
}
No matter what I do it keeps me giving error this.source is not a function. Any help is greatly appreciated
make sure that the countries are filled with data make sync json call if needed.

Resources