I have data being pulled from a db using php and then passed into javascript to load js-grid. I also have a dropdown populated with php containing the default value selected and stored by the user. My goal is to populate the grid with all data returned, then filter it based on the selected option in the dropdown.
I can't seem to understand how to load then filter data using js-grid.
<script type="text/javascript">var order_json = <?= $order_json ?>; var user_list = <?= $user_list['activeListId'] ?>;</script>
<script type="text/javascript" src="js/main.js"></script>
main.js
$( document ).ready(function() {
$("#jsGrid").jsGrid({
width: "100%",
height: "400px",
inserting: false,
editing: false,
sorting: true,
paging: false,
pageSize: 30,
noDataContent: "No orders found",
data: order_json,
fields: [
{ name: "OrderId", type: "number", title: "Order ID", visible: false },
{ name: "ListId", type: "number", title: "Order List ID", visible: true},
{ name: "Name", type: "text", title: "Order Name", align: "left"}
],
});
var grid = $("#jsGrid").data("JSGrid");
grid.search({ListId: user_list})
});
I have tried some different approaches and none have worked. Any help would be appreciated.
With js-grid the actual filtering of the data should be implemented by developer.
The filtering could be done on the client-side or server-side. Client-side filtering implemented in loadData method of controller. Server-side filtering is done by a server script that receives filtering parameters, and uses them to retrieve data.
Here is how your controller.loadData method could look like:
loadData: function(filter) {
var d = $.Deferred();
// server-side filtering
$.ajax({
type: "GET",
url: "/items",
data: filter,
dataType: "json"
}).done(function(result) {
// client-side filtering
result = $.grep(result, function(item) {
return item.SomeField === filter.SomeField;
});
d.resolve(result);
})
return d.promise();
}
As for data option, it's used only for static grid data.
Worth to mention that it would be better to provide data to grid with a REST-y service (of course, it can be done with PHP).
Here is the sample project showing how to use js-grid with a REST service on PHP https://github.com/tabalinas/jsgrid-php.
loadData: function (filter) {
criteria = filter;
var data = $.Deferred();
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: "/api/advertisements",
dataType: "json"
}).done(function(response){
var res = [];
if(criteria.Title !== "")
{
response.forEach(function(element) {
if(element.Title.indexOf(criteria.Title) > -1){
res.push(element);
response = res;
}
}, this);
}
else res = response;
if(criteria.Content !== "")
{
res= [];
response.forEach(function(element) {
if(element.Content.indexOf(criteria.Content) > -1)
res.push(element);
}, this);
}
else res = response;
data.resolve(res);
});
return data.promise();
},
Whenever filtering is involved the function loadData of the controller is called.
There you can implement the filtering functionality that you want.
Here is an example of a generic filter that checks if the string you 've typed in the filter row is contained in your corresponding rows, works with numbers and other types as well
loadData: function (filter) {
return $.get('your.url.here')
.then(result => result.filter(row => Object.keys(filter).every(col =>
filter[col] === undefined
|| ('' + filter[col]).trim() === ''
|| ('' + row[col]).toLowerCase().includes(('' + filter[col]).trim().toLowerCase())
)))
}
If you're not getting your data from a server you can still use the loadData function as described here: https://github.com/tabalinas/jsgrid/issues/759
If you want to invoke filtering manually you can use the search function as described in the docs: http://js-grid.com/docs/#searchfilter-promise
Related
I've set up a Select2 instance that queries my database and renders the results via AJAX on an input that the user has access to.
Everything is working but as this is a location selection input for a user and there are districts and municipalities with same names, for example, I want to add a label for each result to identify them either as "District", "Municipality", "Parish", etc. but I'm unable to do so, I've been unable to find any support on this matter on the Internet and the extension itself doesn't seem to be able to do this,
Select2 AJAX Function
$("#location-property-alert-location").select2({
placeholder: "Type the name of the location",
minimumInputLength: 2,
ajax: {
url: '/ajax/search-locations-by-query',
dataType: 'json',
type: "GET",
data: function data(params) {
return {
query: params.term // search term
};
},
processResults: function processResults(response) {
// return{
// results: response.name
// };
response = response.map(function (item) {
// console.log(item);
return {
id: JSON.stringify(item), // json_encode the data so we can pass this through the ID
code: JSON.stringify(item),
test: "hello",
text: item.location_name
};
});
console.log(response);
return {
results: response
};
},
cache: true
}
});
I know Select2 can take additional data parameters such as the code and test parameters I added above but I don't know how exactly I can use these to create elements within the results with each item's category, for example, as portrayed in the screenshot below.
Each item's category is being stringified so I can pass this data through the form's submission either way but I need to identify each item's category on the frontend for the user to be able to differentiate locations,
Anyone has any idea on how to do this?
Cheers
Note: I don't want Select2's label appearance which basically groups options per category.
You can use templateSelection which will format your selection appearance and then change the result according to your json data.
Below is the demo for how this works with random json data.
function formatResult(item) {
//checks if the id present or not
if (!item.id) {
return item.text;
}
//return the format options..
var element = $(`<span>${item.text}<span class="text_small">${item.username}</span></span>'`)
return element;
};
$("#location-property-alert-location").select2({
placeholder: "Type the name of the location",
minimumInputLength: 2,
ajax: {
url: 'https://jsonplaceholder.typicode.com/users', //this is just for demo...
dataType: 'json',
type: "GET",
data: function data(params) {
return {
query: params.term // search term
};
},
processResults: function processResults(response) {
response = response.map(function(item) {
return {
id: JSON.stringify(item.id),
text: item.name,
username: item.username //pass here extra param
};
});
return {
results: response
};
},
cache: true
},
templateResult: formatResult //your selection format
});
.text_small {
font-size: 10px;
color: grey;
margin-left: 10px;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2#4.1.0-beta.1/dist/css/select2.min.css">
<script src="https://code.jquery.com/jquery-3.5.0.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2#4.1.0-beta.1/dist/js/select2.min.js"></script>
<select id="location-property-alert-location" style="width:300px"></select>
I've gotten xeditable and select2 to work with an api call as the source and everything works great EXCEPT the following.
After submitting the select2 dropdown, the value of the table is displayed as EMPTY and requires a page refresh in order to update to the correct value.
Does anyone know how to update the value to the selected select2 dropdown value?
my html:
<td class="eo_role"><a href="#" data-pk={{r.pk}} data-type="select2" data-url="/api/entry/{{r.pk}}/"
data-name="eo_role" data-title="Enter EO_role">{{r.eo_role}}</a></td>
here is my JS:
$('#example .eo_role a').editable( {
params: function(params) { //params already contain `name`, `value` and `pk`
var data = {};
data[params.name] = params.value;
return data;
},
source: 'http://localhost:8000/api/eo_role/select_two_data/',
tpl: '<select></select>',
ajaxOptions: {
type: 'put'
},
select2: {
cacheDatasource:true,
width: '150px',
id: function(pk) {
return pk.id;
},
ajax: {
url: 'http://localhost:8000/api/eo_role/select_two_data/',
dataType: "json",
type: 'GET',
processResults: function(item) {return item;}
}
},
formatSelection: function (item) {
return item.text;
},
formatResult: function (item) {
return item.text;
},
templateResult: function (item) {
return item.text;
},
templateSelection : function (item) {
return item.text;
},
});
Again - everything works (database updates, dropdownlist populates etc.) however the <td> gets updated with "EMPTY" after submitting the dropdown - requiring a page refresh to show the correct value.
I figured out a workaround. I'm SUPER PUMPED.
//outside of everything, EVERYTHING
//test object is a global holding object that is used to hold the selection dropdown lists
//in order to return the correct text.
var test = {};
$('#example .eo_role a').editable( {
params: function(params) { //params already contain `name`, `value` and `pk`
var data = {};
data[params.name] = params.value;
return data;
},
//MUST be there - it won't work otherwise.
tpl: '<select></select>',
ajaxOptions: {
type: 'put'
},
select2: {
width: '150px',
//tricking the code to think its in tags mode (it isn't)
tags:true,
//this is the actual function that triggers to send back the correct text.
formatSelection: function (item) {
//test is a global holding variable set during the ajax call of my results json.
//the item passed here is the ID of selected item. However you have to minus one due zero index array.
return test.results[parseInt(item)-1].text;
},
ajax: {
url: 'http://localhost:8000/api/eo_role/select_two_data/',
dataType: "json",
type: 'GET',
processResults: function(item) {
//Test is a global holding variable for reference later when formatting the selection.
//it gets modified everytime the dropdown is modified. aka super convenient.
test = item;
return item;}
}
},
});
I faced that same issue. I handle it that way:
In x-editable source code look for:
value2html: function(value, element) {
var text = '', data,
that = this;
if(this.options.select2.tags) { //in tags mode just assign value
data = value;
//data = $.fn.editableutils.itemsByValue(value, this.options.select2.tags, this.idFunc);
} else if(this.sourceData) {
data = $.fn.editableutils.itemsByValue(value, this.sourceData, this.idFunc);
} else {
//can not get list of possible values
//(e.g. autotext for select2 with ajax source)
}
As you can see, there is else statment, without any code (only 2 comments) that is the situation, with which we have a problem. My solution is to add missing code:
(...) else {
//can not get list of possible values
//(e.g. autotext for select2 with ajax source)
data = value;
}
That's fix problem without tags mode enabled. I do not detect any unwanted behaviors so far.
Example code:
jQuery('[data-edit-client]').editable({
type: 'select2',
mode: 'inline',
showbuttons: false,
tpl: '<select></select>',
ajaxOptions: {
type: 'POST'
},
select2: {
width: 200,
multiple: false,
placeholder: 'Wybierz klienta',
allowClear: false,
formatSelection: function (item) {
//test is a global holding variable set during the ajax call of my results json.
//the item passed here is the ID of selected item. However you have to minus one due zero index array.
return window.cacheData[parseInt(item)].text;
},
ajax: {
url: system.url + 'ajax/getProjectInfo/',
dataType: 'json',
delay: 250,
cache: false,
type: 'POST',
data: {
projectID: system.project_id,
action: 'getProjectClients',
customer: parseInt(jQuery("[data-edit-client]").attr("data-selected-company-id"))
},
processResults: function (response) {
window.cacheData = response.data.clients;
return {
results: response.data.clients
};
}
}
}
});
I tried build custom validator for jsgrid that check the item.Name is really exist from DB or not before inserting or Editing to avoid any duplicated row.
the problem I read three times the Documents of jsgrid but I didn't get any idea how to fix the problem.
this work https://github.com/tabalinas/jsgrid-php helped me too much and I transformed to be useful for my work and to mysqli.
the idea:
I made function check DB if the value exist or not, if exist it return true else false in a php class
public function checkName($name){
try{
if(!empty($name)){
$co_conn = $this->CON_conn->open_connect();
$getsame = mysqli_query($co_conn,"select Name from category where Name = '$name'");
if($getsame){
$numit = mysqli_num_rows($getsame);
if($numit > 0) return true;
else return false;
}
else return true;
$this->CON_conn->close_connect($co_conn);
}
else return true;
}
catch(Exception $er){
return true;
}
}
and I called this function in an external file "CheckValue.php"
<?php require_once '////the director of the class';
$chnow = new NameOfMyClass();
$result = true;
switch($_SERVER["REQUEST_METHOD"]) {
case "CHGO":
parse_str(file_get_contents("php://input"), $_CHGO);
//to ensure if it work i tested it.
$result = $chnow->checkName($_CHGO["Name"]);
break;
default:
$result = true;
break;
}
header('Content-type: application/json');
echo json_encode($result);
?>
in basic.html
$(function() {
$.ajax({
type: "GET",
url: "../bin/update.php"
}).done(function(response) {
response.unshift({ ID: "0", Name: "" });
$("#jsGrid").jsGrid({
height: "50%",
width: "70%",
selecting: false,
filtering: false,
editing: false,
sorting: false,
paging: true,
autoload: true,
pageSize: 15,
pageButtonCount: 5,
controller: {
loadData: function(filter) {
return $.ajax({type:"GET", url: "../bin/update.php",data:filter});
},
updateItem: function(item) {
return $.ajax({type:"PUT",url: "../bin/update.php",data: item});
},
insertItem: function(item) {
/*$.ajax({type: "CHGO",url: "..bin/Checkvalue.php",data:item.Name, dataType: "json",
success: function(data){
JSON.parse(data);
consol.log(data);
//alert(data);
//I used many ways to find why its not work, then I commented it
}
});
//return $.ajax({type: "POST",url: "../bin/update.php",data: item});
//return data;
//else sweetAlert("error", "this value is exist!", "error");
//here I thought merge sweetalert js will give a good look of work not the normal message.
*/
}
},
fields: [
{ name: "ID", type: "number",width: 50, editing:false, inserting:false },
{ name: "Name", type: "text", width: 50, validate: ["required",{
message: "this value is exist",
validator: function(value,item){
if(value != "")
{
$.ajax({
type: "CHGO",
url: "..bin/Checkvalue.php",
data: item.Name,
success: function(data){
if(data == true)
//I assume here return the true/false to activate the error message but nothing work..sorry
}
});
}
}
} ]
},
{ type: "control", modeSwitchButton: false, deleteButton: false }
]
});
});
$(".config-panel input[type=checkbox]").on("click", function() {
var $cb = $(this);
$("#jsGrid").jsGrid("option", $cb.attr("id"), $cb.is(":checked"));
});
});
please help, I 'm try for 2 days to fix the problem.
thanks for the developers for writing the validate js file
I used jsgrid-1.4.1
The reason is that validate supports only synchronous validation, and validation from our example requires ajax call, so it's asynchronous.
You have two options:
Load data to the client beforehand and validate inserting item on the client (so validation will be synchronous)
Validate insertion in insertItem method. Checkout the following issue to know more details https://github.com/tabalinas/jsgrid/issues/190
I have a Kendo Grid that loads data via ajax with a call to server-side ASP.NET read method:
public virtual JsonResult Read(DataSourceRequest request, string anotherParam)
In my client-side JS, I trigger a read when a button is clicked:
grid.dataSource.read( { anotherParam: 'foo' });
grid.refresh();
This works as expected, only I lose the additional param when I move through the pages of results in the grid, or use the refresh icon on the grid to reload the data.
How do I persist the additional parameter data in the grid?
I have tried setting
grid.dataSource.data
directly, but without much luck. I either get an error if I pass an object, or no effect if I pass the name of a JS function that returns data.
if you want to pass additional parameters to Read ajax datasource method (server side), you may use
.DataSource(dataSource => dataSource
...
.Read(read => read.Action("Read", controllerName, new { anotherParam= "foo"}))
...
)
if you want to pass additional parameters through client scripting you may use datasource.transport.parameterMap, something as below
parameterMap: function(data, type) {
if (type == "read") {
return { request:kendo.stringify(data), anotherParam:"foo" }
}
Use the datasource.transport.parameterMap
parameterMap: function(data, type) {
if (type == "read") {
return kendo.stringify(data, anotherParam);
}
I'm not sure where your other param is coming from, but this is generally how I send extra parameters to the server.
http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-transport.parameterMap
if use datasource object :
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: '/Api/GetData',
contentType: "application/json; charset=utf-8", // optional
dataType: "json",
data: function () {
return {
additionalParam: value
};
}
},
//parameterMap: function (data, type) {
// and so use this property to send additional param
// return $.extend({ "additionalParam": value }, data);
//}
},
schema: {
type: "json",
data: function (data) {
return data.result;
},
},
pageSize: 5,
serverPaging: true,
serverSorting: true
});
and set options in grid:
$("#grid").kendoGrid({
autoBind: false,
dataSource: dataSource,
selectable: "multiple cell",
allowCopy: true,
columns: [
{ field: "productName" },
{ field: "category" }
]
});
and in click event this code :
dataSource.read();
and in api web method this action:
[HttpGet]
public HttpResponseMessage GetData([FromUri]KendoGridParams/* define class to get parameter from javascript*/ _param)
{
// use _param to filtering, paging and other actions
try
{
var result = Service.AllCustomers();
return Request.CreateResponse(HttpStatusCode.OK, new { result = result });
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.BadRequest, new { result = string.Empty });
}
}
good luck.
To persist the updated value of the additional parameter through pagination, you will need to create a global variable and save the value to it.
var anotherParamValue= "";//declare a global variable at the top. Can be assigned some default value as well instead of blank
Then, when you trigger the datasource read event, you should save the value to the global variable we created earlier.
anotherParamValue = 'foo';//save the new value to the global variable
grid.dataSource.read( { anotherParam: anotherParamValue });
grid.refresh();
Now, this is important. In your datasource object transport.read.data must be set to use a function as shown below:
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: '/Api/GetData',
contentType: "application/json; charset=utf-8", // optional
dataType: "json",
//Must be set to use a function, to pass dynamic values of the parameter
data: function () {
return {
additionalParam: anotherParamValue //get the value from the global variable
};
}
},
},
schema: {
type: "json",
data: function (data) {
return data.result;
},
},
pageSize: 5,
serverPaging: true,
serverSorting: true
});
Now on every page button click, you should get the updated value of the anotherParam which is currently set to foo
I am trying to work with the Select2 plugin in conjunction with the CodeIgniter framework. After a lot of effort, I managed to get it to work with AJAX data. However, now it has a weird problem. Even after typing in the entire name, the plugin does not eliminate the irrelevant options that do not match with the search term.
The below screenshot depicts this.
http://i.imgur.com/MfLcuf6.jpg?1
The Firebug console looks like this:
http://i.imgur.com/Qvko6mX.jpg
Below is my the Javascript code as well as the code for my controller
Javascript:
$("#mentor-typeahead").select2({
width: "100%",
placeholder: "Enter a mentor name",
maximumSelectionSize: 5,
minimumInputLength: 2,
multiple: true,
ajax: {
url: 'get_mentor_multi_list',
quietMillis: 500,
cache: true,
dataType: 'json',
results: function (data) {
return { results: data };
}
}
});
Controller
function get_mentor_multi_list($query = null)
{
$answer = array(array('id'=>1, 'text'=>'Inigo Montoya'),
array('id'=>2, 'text'=>'Zoey Deschanel'),
array('id'=>3, 'text'=>'Harry Potter'),
array('id'=>4, 'text'=>'Nicole Scherzinger'),
array('id'=>5, 'text'=>'Xerxes Mistry'),
array('id'=>6, 'text'=>'Tom Marvollo Riddle'),
array('id'=>7, 'text'=>'Light Yagami'),
array('id'=>8, 'text'=>'Vic Mackey'),
array('id'=>9, 'text'=>'Clark Kent'));
echo json_encode($answer);
}
I am utterly confused as to what could be causing the problem. I also tried the solution listed here link but to no avail. Any help would be appreciated.
Changed the AJAX call parameters on request but the output remains the same...
$("#mentor-typeahead").select2({
width: "100%",
placeholder: "Enter a mentor name",
maximumSelectionSize: 5,
minimumInputLength: 2,
multiple: true,
ajax: {
url: 'get_mentor_multi_list',
quietMillis: 200,
dataType: 'json',
data: function (term, page) {
return {
q: term,
page_limit: 10
};
},
results: function (data, page) {
return data;
}
}
You're missing a data function in the ajax part. See Loading Remote Data and Infinite Scroll with Remote Data in the documentation.
ajax: {
url: "http://api.rottentomatoes.com/api/public/v1.0/movies.json",
dataType: 'jsonp',
quietMillis: 100,
data: function (term, page) { // page is the one-based page number tracked by Select2
return {
q: term, //search term
page_limit: 10, // page size
page: page, // page number
apikey: "ju6z9mjyajq2djue3gbvv26t" // please do not use so this example keeps working
};
},
results: function (data, page) {
var more = (page * 10) < data.total; // whether or not there are more results available
// notice we return the value of more so Select2 knows if more results can be loaded
return {results: data.movies, more: more};
}
}
You're not using the ajax function correctly. It's doing exactly what it's supposed to do and that is to display all of the data returned from your get_mentor_multi_list() function.
In order to do this correctly, your ajax call needs to include a data attribute that includes parameters to be sent to your get_mentor_multi_list() function. get_mentor_multi_list() will then return only the results that your user is looking for.
If the data in get_mentor_multi_list() is static (i.e. not read from any database), you should consider adding it to the data attribute like in the Loading Array Data example here.
Finally, I was able to resolve the problem by myself. The problem lay in the fact that I was using CodeIgniter. Hence whatever variables that were supposed to be passed through the data attribute of the AJAX call weren't actually being passed to the controller.
I resolved this by changing the Javascript code to the following:
JavaScript
$('#mentor-typeahead').select2({
width: "100%",
placeholder: "Enter a mentor name",
maximumSelectionSize: 5,
minimumInputLength: 2,
multiple: true,
ajax: {
url: 'get_mentor_multi_list',
quietMillis: 200,
dataType: 'json',
data: function (term, page) {
return {
searchq: term // set the search term by the user as 'searchq' for convenient access
};
},
results: function (data, page) {
return {
results: data
};
}
}
});
And the controller code to look something like the following:
function get_mentor_multi_list()
{
// model code
$query = trim($_GET['searchq']); // get the search term typed by the user and trim whitespace
if(!empty($query))
{
// retrieve data from database
}
else
{
$answer = array('id' => 0, 'text' => 'No results found');
}
echo json_encode($answer);
}