How to use server-side pagination with ajax in bootstrap-table? - spring-mvc

I am looking for a way to implement the server-side (paginationdata-side-pagination="server") for bootstrap-table with spring mvc. I want to retrieve data from the controller partially based on the pagination page id clicked by the user. I searched a lot but couldn't find any good resource on this through the internet.

Hope this helps:
$(document).ready(function(){
ajaxGet();
});
function ajaxGet(){
var table_params = $('#docs_table').bootstrapTable({
url: 'ajax/test_1/data?',
queryParams: function (p) {
return {
limit: p.limit,
offset: p.offset,
sort: p.sort,
order: p.order,
search: p.search,
'data[]': [other data],//for multi-select filter
};
}
});
$('#docs_table').bootstrapTable('refresh');
}
You will receive parameters on server side as following:
Parameters for paging
Limit -- $_GET['offset']
Offset -- $_GET['offset']
Parameters for data manipulation
Search -- $_Get['search']
Sort -- $_Get['sort']
Order -- $_Get['order']
Reference:: Python example

Related

How do I handle values that are dependent on the result of a helper?

So I have an Angular controller with a meteor helper method, as below.
function localeCtrl($scope, $reactive, $stateParams{
$reactive(this).attach($scope);
var self = this;
self.helpers({
locale: function(){ return Locales.findOne($stateParams.id)},
staff: function(){
// Load data from second collection based on current Locale.
// But how?
},
address: function(){
// Take self.location.address and massage it to provide
// google maps link. How?
}
tags: function(){
// Collect all unique instances of a given tag by
// iterating over the available locales.
// E. G. If 10 locales have the 'restaurant' tag, and 5
// more have the 'library' tag, I want an array of
// ['restaurant', 'library'] -- easy enough to do
// by iterating over the locales, but how do I do that
// reactively?
}
});
}
Unfortunately, I need to set additional properties based on the data fetched by locale(). I can't set them up when I initialize the controller because the value in locale() changes as data is fetched from the server. But I need access to the data in locale to, for example, create the google maps address, or fetch associated records. (They aren't imbedded in the locale document for reasons that I'm sure made sense at the time).
Edit:
Additionally, I'm using ground DB to store a local copy of the data for offline access, which makes life even more complicated.
Probably you best bet is to publish your collection using publishComposite which is implemented using the reywood:publish-composite package.
Add the package:
meteor add reywood:publish-composite
Now where you publish the Locales collection you would do something like this:
Meteor.publishComposite('locales', function() {
return {
find() {
//Put whatever you need in the query for locales
const query = {
_userId: this.userId
};
return Locales.find(query);
},
children: [{
find(locale) {
return Staff.find({ localeId: locale._id });
}
}]
};
});
Then in your controller before the helper you add this:
this.subscribe('locales');
Now you should be able to simply call the code like this:
this.helpers({
locale(){
return Locales.findOne(this.$stateParams.id);
}
});
And access it in the template like this:
locale.staff
Give that a try and let me know!

Best practice for meteor dynamic subscription

Is it possible to do something like "filtered subscription" in Meteor: for example if you have a filter on month june and switching to july fetches the new data and subscribes to it?
i tried something like:
Meteor.publish("report", function (query, opt) {
return Report.find({ 'timestamp' : { $gte : query.from, $lt: query.to }}, options);
}
on client with iron router:
HomeController=RouteController.extend({
template:"home",
waitOn:function(){
var dates = getDates();
return Meteor.subscribe("report", dates);
},
fastRender: true
});
but it does not work.
Is there a better method to dynamically subscribe? Or does it just help to navigate with url pattern?
thanks
Is there a better method to dynamically subscribe?
There is an alternative method using template subscriptions, example below. I don't think it's better, just different.
Or does it just help to navigate with url pattern?
If you want to handle the subscriptions in the Router, then storing the subscription query params in the URL does help and has some added benefits in my opinion. But it depends on your desired app behavior.
Using Template Subscriptions approach :
This Meteor Pad example will subscribe to a range of data based on a select :
http://meteorpad.com/pad/26dd8YQevBbA5uNGA/Dynamic%20Subscription
Using Iron Router approach :
This route example will subscribe based on the URL . "items/0/10" will subscribe to the itemData with a range of zero to 10.
Router.route('Items', {
name:'Items',
path:'items/:low/:high',
subscriptions : function(){
var low = parseInt(this.params.low);
var high = parseInt(this.params.high);
return [
Meteor.subscribe("itemData",low,high),
];
},
action: function () {
if (this.ready()) {
this.render();
} else {
this.render('Loading');
}
}
});
I think either approach is fine and depends on your interface. Using the URL is nice because you can provide links directly to the range of data, use forward and back buttons in browser, good for paging lists of data.
The template subscriptions approach might be appropriate to change the data on a graph.
The specific issue you are having might be due to the fact that your getDates() is not reactive, so the subscription is only run once when the route waitOn is first run.

Customize Kendo DataSource's OData URL?

I'm using a Kendo Grid pointed to an ASP.NET Web API OData controller. I'm wondering if it's possible to customize/overwrite the generated OData URL that Kendo's DataSource generates? My issue is my date fields are DateTimeOffset and I'm trying to sort by those fields, however Kendo's model fields only support string/bool/number/date, nothing for DateTimeOffset. The URL it generates for date fields is:
http://localhost/api/odata/customers?%24inlinecount=allpages&%24top=10&%24filter=(CreatedDate+ge+datetime%272015-01-01T00%3A00%3A00%27) which fails.
It should be:
http://localhost:900/api/odata/customers?%24inlinecount=allpages&%24top=10&%24filter=(CreatedDate+ge+datetimeoffset%272015-01-01T00%3A00%3A00%27)
Is it possible to force it to use datetimeoffset instead?
You are probably not using the right "odata" transport. Try with "odata-v4". More info is available here.
For my ASP.NET Web API 2's OData V4 controllers, I actually need this URL format:
http://localhost:XX/odata/Things?$filter=DteTmOfsField eq 2012-12-03T07:16:23Z
And this javascript is working pretty good for me:
$(document).ready(function () {
$("#grid").kendoGrid({
dataSource: {
type: "odata-v4",
transport: {
read: {
url: "/odata/Things/",
dataType: "json"
},
parameterMap: function (options,type) {
var paramMap = kendo.data.transports.odata.parameterMap(options, type);
if (paramMap.$filter) {
paramMap.$filter = paramMap.$filter.replace(/datetime'([-0-9T:]{19})'/gi, "$1Z");
}
paramMap.$count = true;
delete paramMap.$inlinecount; // <-- remove inlinecount parameter
delete paramMap.$format; // <-- remove format parameter
return paramMap;
}
},

How to 'transform' data returned via a Meteor.publish?

Meteor Collections have a transform ability that allows behavior to be attached to the objects returned from mongo.
We want to have autopublish turned off so the client does not have access to the database collections, but we still want the transform functionality.
We are sending data to the client with a more explicit Meteor.publish/Meteor.subscribe or the RPC mechanism ( Meteor.call()/Meteor.methods() )
How can we have the Meteor client automatically apply a transform like it will when retrieving data directly with the Meteor.Collection methods?
While you can't directly use transforms, there is a way to transform the result of a database query before publishing it. This is what the "publish the current size of a collection" example describes here.
It took me a while to figure out a really simple application of that, so maybe my code will help you, too:
Meteor.publish("publicationsWithHTML", function (data) {
var self = this;
Publications
.find()
.forEach(function(entry) {
addSomeHTML(entry); // this function changes the content of entry
self.added("publications", entry._id, entry);
});
self.ready();
});
On the client you subscribe to this:
Meteor.subscribe("publicationsWithHTML");
But your model still need to create a collection (on both sides) that is called 'publications':
Publications = new Meteor.Collection('publications');
Mind you, this is not a very good example, as it doesn't maintain the reactivity. But I found the count example a bit confusing at first, so maybe you'll find it helpful.
(Meteor 0.7.0.1) - meteor does allow behavior to be attached to the objects returned via the pub/sub.
This is from a pull request I submitted to the meteor project.
Todos = new Meteor.Collection('todos', {
// transform allows behavior to be attached to the objects returned via the pub/sub communication.
transform : function(todo) {
todo.update = function(change) {
Meteor.call('Todos_update', this._id, change);
},
todo.remove = function() {
Meteor.call('Todos_remove', this._id);
}
return todo;
}
});
todosHandle = Meteor.subscribe('todos');
Any objects returned via the 'todos' topic will have the update() and the remove() function - which is exactly what I want: I now attach behavior to the returned data.
Try:
let transformTodo = (fields) => {
fields._pubType = 'todos';
return fields;
};
Meteor.publish('todos', function() {
let subHandle = Todos
.find()
.observeChanges({
added: (id, fields) => {
fields = transformTodo(fields);
this.added('todos', id, fields);
},
changed: (id, fields) => {
fields = transformTodo(fields);
this.changed('todos', id, fields);
},
removed: (id) => {
this.removed('todos', id);
}
});
this.ready();
this.onStop(() => {
subHandle.stop();
});
});
Currently, you can't apply transforms on the server to published collections. See this question for more details. That leaves you with either transforming the data on the client, or using a meteor method. In a method, you can have the server do whatever you want to the data.
In one of my projects, we perform our most expensive query (it joins several collections, denormalizes the documents, and trims unnecessary fields) via a method call. It isn't reactive, but it greatly simplifies our code because all of the transformation happens on the server.
To extend #Christian Fritz answer, with Reactive Solution using peerlibrary:reactive-publish
Meteor.publish("todos", function() {
const self = this;
return this.autorun(function(computation) {
// Loop over each document in collection
todo.find().forEach(function(entry) {
// Add function to transform / modify each document here
self.added("todos", entry._id, entry);
});
});
});

ASP.NET MVC: Save multiple values on autocomplete

I have a mysql database with the tables "deliverables", "tags" and "deliverables_has_tags". I want to link tags to a deliverable.
This is what I do in my javascript file:
<script type="text/javascript" language="javascript">
$(function () {
var object = {};
$.ajax({
type: "GET",
url: "/Deliverable/Tags",
dataType: "json",
success: function (data) {
object.tags = data;
}
});
function split(val) {
return val.split(/,\s*/);
}
function extractLast(term) {
return split(term).pop();
}
$("#tags")
// don't navigate away from the field on tab when selecting an item
.bind("keydown", function (event) {
if (event.keyCode === $.ui.keyCode.TAB &&
$(this).data("ui-autocomplete").menu.active) {
event.preventDefault();
}
})
.autocomplete({
minLength: 0,
source: function (request, response) {
// delegate back to autocomplete, but extract the last term
response($.ui.autocomplete.filter(
object.tags, extractLast(request.term)));
},
focus: function () {
// prevent value inserted on focus
return false;
},
select: function (event, ui) {
var terms = split(this.value);
// remove the current input
terms.pop();
// add the selected item
terms.push(ui.item.value);
// add placeholder to get the comma-and-space at the end
terms.push("");
this.value = terms.join(", ");
return false;
}
});
});
</script>
I can add multiple tags in my textbox.
But now I want to save this in my repository.
In my Action method in controller:
repository.AddDeliverable(model.Title, model.Description, model.UsernameID, data, datatwo, model.VideoUrl, model.AfstudeerrichtingID, model.ProjectID);
Tags action:
public JsonResult Tags()
{
var data = (repository.GetTags()).ToArray();
return Json(data, JsonRequestBehavior.AllowGet);
}
In my repository:
public IQueryable<string> GetTags()
{
return from tag in entities.tags
orderby tag.tag_name
select tag.tag_name;
}
I have no clue how to save this in my database.
Can anybody help me?
If I correctly understood your question, you have implemented your tag handling as follows:
There is MVC action method that returns the view with input placeholder containing no data
The placeholder itself is probably input type=text with id=tags
On 'dom ready' you fire ajax request to retrieve your tags from database, json-serialized as array; when it arrives you store it to tags variable (no error handling(!))
At the same time you decorate your input with jqueryui autocomplete that reacts on user input and returns items from the tags variable
Since input already contains tags (comma separated), your filter is first letters of the last tag
So, you have a situation when user has input a few comma separated tags (probably some of them can be new) and now wants to save it to the database. For each input, if that is a known tag you have to store it to "deliverables_has_tags". If there is a new tag, you have to store it both to "tags" and "deliverables_has_tags".
Most common scenario would be having a 'Save' button to start saving process.
Let's analyze what you have to do in the process.
1) Button click
On button click you use js to convert your comma separated tags string
using logic like split(term) to the array, and serialize it. You can
do serialization using serializeArray and manually create JSON
object, or serialize the whole form using
$('#yourForm').serialize(). I would choose the first option
because that way I get more control over JSON format and avoid
problems with MVC default model binder.
2) Ajax call
When the JSON object is ready to be sent, you fire an ajax POST
request to your MVC POST action method. When you save state always
avoid GET because new versions of browsers can scan thru your page and
actively preload urls using GET requests. You don't want this here. Of
course, use your data as a data-parameter in the ajax call.
3) Action method
When the request arrives, you have to process it in your controller
using a new action method. Typically in this case you will have
something like public JsonResult SaveTags(SaveTagsModel saveTags) {
... } which saves tags using your repository and returns result that
says something like 'OK' or 'ERROR' (sth like
response.isSaved=true/false). Tricky part can be designing view model
according to your JSON object - this could help. And regarding
collections this could be valuable info.
When saving, use transaction to ensure everything is saved at once.
First check if each tag exists in the database and insert those who
don't exist. After that, check for each tag if there is appropriate
n-n relation in deliverables_has_tags and insert it if there isn't.
I believe that you should use same repository encapsulation for both
operations.
In the post action, include FormCollection collection as argument and gather your tags from that. There is no automatic way. You could implement some custom model binding, but that is probably not worth the effort.

Resources