Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client side filtering when using controller as source #32

Closed
sanurocks opened this issue May 20, 2015 · 33 comments
Closed

Client side filtering when using controller as source #32

sanurocks opened this issue May 20, 2015 · 33 comments

Comments

@sanurocks
Copy link

  1. I am unable to enable client side filtering when using rest as data source. Is this the intended behavior? i would like to know if we can have both client filtering as well as controller post filtering the case being use the search button for controller post filtering and the keypress up/down event as client side filtering.
  2. Is is possible to extract the filtered json after filtering not the full json considering filtering can be enabled client side. I can see there is onDataLoaded event which can be used but it will work with full post.

So basically two types of filtering and two types of json extraction is what i have in mind.

Any help is appreciated.

@tabalinas
Copy link
Owner

Client-side filtering and server-side filtering are completely on shoulders of developer.
Client-side filtering implemented in loadData method of controller. Server-side apparently implemented with server script that receives filtering parameters, and uses them to fetch data, and pass to client.
That's why you can use client-side and server-side filtering at the same time.
Here is how your controller.loadData method could look like in this case:

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();
}

Hope it will help.

@sanurocks
Copy link
Author

  1. I get it. But tell me one thing in the above code also everytime the filter is first passed to server, the server sends the json and the additional filter is set via the client code. My specific scenario is that the plugin auto loads data once from the server which it does, then when i use filter i want the filter to happen on client side only not post the filter to server. And then i want the json of the filtered data. Like how it happens in the basic example of the plugin, the filter works instantly without posting or so it seems. Is it only possible via using static data and not dynamic data?

So what i want is dataset to be loaded only once during initialization and all filtering and extracting filtered json on client side.

  1. Also is there any way to disable fields [columns] from client side. Like server returned 10 field, show the 10 field by default but then via a dropdown multi selection show only the selected columns and vice versa.
  2. I was fiddling around and if i change the with of parent container the headers are resized properly but the content is at its previous width.
  3. How to consume the onDataLoaded event and how to get the jsgrid instance?

Sorry for so many questions, I am new to this. Thankyou.

@tabalinas
Copy link
Owner

  1. Yes, there is a way for static scenario - just provide data to data option. You can find a demo on the demos page http://js-grid.com/demos/ For instance, you could initialize jsgrid on done of first ajax request.
  2. Also is there any way to disable fields - change the option fields depending on your select
$("#jsGrid").jsGrid("option", "fields", fields); // here fields array depends on your multiselect
  1. the content is at its previous width call refresh method
$("#jsGrid").jsGrid("refresh");
  1. How to consume the onDataLoaded event - just pass the callback function
$("#jsGrid").jsGrid({
   onDataLoaded: function(args) {
      // data is loaded, so do whatever you want, here you have also access to loaded data with args.data
   }
});
  1. get the jsgrid instance - get it from element data by key JSGrid or in any callback from args.grid
var grid = $("#jsGrid").data("JSGrid");

However, I'm not sure why you need it. You can set any option and call any method using jQuery element.

@sanurocks
Copy link
Author

Even after providing json data to data field the plugin is posting to server for filtering. here is my initialization code. all i want is client side filtering.

$.get('@Url.Action("Action", "Controller")', function(reportJson) {
$("#jsGrid").jsGrid({
width: "100%",
height: "470px",

        heading: true,
        filtering: true,
        inserting: false,
        editing: false,
        selecting: false,
        sorting: true,
        paging: true,
        pageLoading: false,

        data: reportJson,

        autoload: false,
        controller: {
            loadData: null,
            insertItem: null,
            updateItem: null,
            deleteItem: null
        },
        fields: [
            { title: "Email Id", name: "UserEmailId", type: "text", width: 200, autosearch: true },
            { title: "Employee Id", name: "EmployeeId", type: "text", autosearch: true },
            { title: "Name", name: "UserName", type: "text", autosearch: true },
            { type: "control", editButton: false, deleteButton: false, modeSwitchButton: false }
        ],

        noDataContent: "No Users In The System",

        confirmDeleting: true,
        deleteConfirm: "Are you sure?",

        pagerContainer: null,
        pageIndex: 1,
        pageSize: 10,
        pageButtonCount: 15,
        pagerFormat: "Pages: {first} {prev} {pages} {next} {last}    {pageIndex} of {pageCount}",
        pagePrevText: "Prev",
        pageNextText: "Next",
        pageFirstText: "First",
        pageLastText: "Last",
        pageNavigatorNextText: "...",
        pageNavigatorPrevText: "...",

        loadIndication: true,
        loadIndicationDelay: 500,
        loadMessage: "Fetching Reports...",
        loadShading: true,
        updateOnResize: true
    });
});

Also please tell me how to extract the filtered json/data?

Rest all is solved.

@tabalinas
Copy link
Owner

Try following approach: don't use data option and use loadData to filter on the client side.
See following code:

$.get('@Url.Action("Action", "Controller")', function(reportJson) {
    $("#jsGrid").jsGrid({
        width: "100%",
        height: "470px",

        heading: true,
        filtering: true,
        inserting: false,
        editing: false,
        selecting: false,
        sorting: true,
        paging: true,
        pageLoading: false,

        autoload: true,
        controller: {
            loadData: function(filter) {
                return $.grep(reportJson, function(item) {
                     // do filtering
                });
            } 
        },

@sanurocks
Copy link
Author

Sorry for being a noob. The above snippet gives me the noDataContent message. i want the functionality to be the same as you have provided in the Demo - Basic scenario. but the code there does not show controller block. i am not used to client side code. Can you please share the controller block of that demo that will solve my issue.

And please tell how to extract the filtered data.

@chenghsuan
Copy link

You can download jsGrid (file link), and it has fully demo code.

@sanurocks
Copy link
Author

Thankyou that solves everything.

@bluelinemango
Copy link

hi!
sry for open again this issue.
i've a problem with filtering in load data in Json way!
i dont know how to do it to work correctly.
plz help me ! i wanna get my data dynamically and set client-side filtering
here my part of code:
var db = {
loadData: function(filter) {
return $.ajax({
type: "POST",
url: "/client/load-json-list",
data: filter,
dataType: "json"
}).success(function(filter) {
FormsSwitchery.init();
})

            },

@zopyx
Copy link

zopyx commented Apr 20, 2016

Here is some example code for generic client side filtering

            DATA = null;

            function load_data(filter) {
                console.log(filter);
                if (DATA == null) {
                    var url = URL + "/@@logger-entries";
                    $.ajax({
                        url: url,
                        dataType: 'json',
                        async: false,
                        method: 'GET',
                        success: function(result) {
                            DATA = result;
                        } 
                    });
                }

                var result = $.grep(DATA, function(item, idx) {
                    for (var key in filter) {
                        var value = filter[key];
                        if (value.length > 0) {
                            if (item[key].indexOf(value) == -1)
                                return false;
                        }
                    }
                    return true;
                });
                return result;
            }

@Akakrlos
Copy link

Akakrlos commented Jun 9, 2016

Hi, im' trying to use ajax request with pagin but dont work

image

$(function () {
        $("#jsGrid").jsGrid({
            height: "80%",
            width: "100%",
            autoload: true,
            paging: true,
            pageLoading: true,
            pageSize: 10,
            pageIndex: 1,
            controller: {
                loadData: function (filter) {
                    var def = $.Deferred();
                    $.ajax({
                        contentType: "application/json",
                        dataType: "json",
                        url: "/api/sportbooks/" + filter.pageIndex + "/" + filter.pageSize
                    }).done(function (response) {
                        def.resolve({
                            data: response.Rows,
                            itemsCount: 500
                        });
                    });

                    return def.promise();
                }
            },
            fields: [
                { name: "Id", type: "number", width: 50, },
                { name: "Name", type: "text", width: 100 },
                { name: "Address", type: "text", width: 100 },
                { name: "PhoneNumber", type: "text", width: 100 },
                { name: "email", type: "text", width: 100 },
                { name: "ContactName", type: "text", width: 100 }
            ]
        });

        $("#pager").on("change", function () {
            var page = parseInt($(this).val(), 10);
            $("#jsGrid").jsGrid("openPage", page);
        });

    });

@tabalinas
Copy link
Owner

Try to put fixed height (e.g. height: 400px), maybe grid is just collapsed due to inappropriate css, since your code looks correctly. Anyway, this issue has different topic, so if you still have a problem, please, open another issue.

@swordsreversed
Copy link

swordsreversed commented Jan 1, 2017

For anyone looking for a case insensitive regex implementation here's mine:

loadData: function (filter) {
        var d = $.Deferred();
        $.ajax({
          type: 'GET',
          url: ajax_url,
          dataType: 'json'
        }).done(function (result) {
          for (var prop in filter) {
            if (filter[prop].length > 0) {
              result = $.grep(result, function (item) {
                var regexp = new RegExp(filter[prop], 'gi');
                if (item[prop].match(regexp)) {
                  return item;
                }
              });
              break;
            }
          }
          d.resolve(result);
        });
        return d.promise();
      }

@wzhao6898
Copy link

Hi, sorry about re-opening this issue. I'm new to jsGrid. I understand that the implementation of client-side or service-side filtering fall on developers, but why not provide function that will take different strategies for client-side, server-side filter, etc.? In the above example for server side filter, why do I need to iterate through the server-side filtered result one more time before display the results?
Thanks,

David

@tabalinas
Copy link
Owner

@wzhao6898, my example above is really how to use server-side and client-side filter at the same time. In most cases you would use only server-side, or sometimes client-side filtering.

There cannot be a "function for server-side" filtering (as you put it), since server-side filtering happens on the server.
For client-side, yes it could be built-in, but from my practice standard filtering would work only for "hello world" scenarios, you need custom logic for a production-ready usage. So you would end up implementing it anyway. Another point is the consistent behavior in sense of mixing server-side and client-side filtering. You get maximum flexibility this way.

@zopyx
Copy link

zopyx commented Apr 9, 2017

But there should be reasonable support for client-side filtering...the current support for client-side filtering is incomplete as clearly described. Don't be a dick...

@tabalinas
Copy link
Owner

tabalinas commented Apr 14, 2017

@zopyx, GitHub is a very respectful place, so please avoid profanity.
It would be better to share your vision on the matter in a constructive way.

Let me explain my point of view:
I created js-grid long long ago, long before open-sourcing it. So it was born from my real use cases - having a grid representation of some data with ability to perform CRUD operations.

From my use cases filtering seemed way more flexible when it's not embedded in the representation component. In fact no data manipulation is embedded. Even sorting is kinda a separate part.
For instance filtering for a select control: how would you define empty filter? Is it particular item? Which one? Empty value? 0? -1? Do you want to compare with equals? contains? startsWith?
There are so many questions that describing filtering would require plenty of configuration parameters to set it. While it's so easy to express with a single filtering function.
Moreover, as I mentioned already, filtering could be done on the server. What then? You need an option to turn off client-side filtering. What if you want to mix filtering partially filtering on the server and then do some filtering on the client? How would you express it?

For me there were way more questions, it seemed easier just let a user to define the filtering function. Also the component mission is to be lightweight. That's why I'm trying to avoid too many built-in features.

Anyways, this is an open source free project. So if you don't like it, just pick up something that works better for you. No need to offend the author for the stuff he shared for free.

@maurorulli
Copy link
Contributor

@zopyx the author is certainly a better person than you. When you'll do something good for strangers, and do not offend them, then you can understand you are out of context here.

@zopyx
Copy link

zopyx commented Apr 15, 2017

Stop blathering. The maintainer has no feeling for obvious design issues or lack of support for this particular problem where lots of people need to do their own workaround.

@maurorulli
Copy link
Contributor

You mean implementation... If you don't like look for better tools elsewhere. No one impose you JsGrid.
Best luck.

@zopyx
Copy link

zopyx commented Apr 15, 2017

@maurorulli move on, you are not participating in this particular issaue

@zopyx
Copy link

zopyx commented Apr 15, 2017

And yes, I moved on to other solutions that are better maintained and where the maintainer is willing to discuss issues instead of appearing like an ignorant brick.

@maurorulli
Copy link
Contributor

Enjoy

@dewelloper
Copy link

dewelloper commented Aug 28, 2017

for everyone..

                        loadData: function (filter) {
                            criteria = filter;
                            var data = $.Deferred();
                            $.ajax({
                                type: "GET",
                                contentType: "application/json; charset=utf-8",
                                url: "/fapplications",
                                dataType: "json"
                                }).done(function(response){
                                    var res = [];
                                    if(criteria.Name !== "")
                                    {
                                        response.forEach(function(element) {
                                            if(element.Name.indexOf(criteria.Name) > -1){
                                                res.push(element);
                                                response = res;
                                            }
                                        }, this);
                                    }
                                    else res = response;
                                    if(criteria.Title !== "")
                                    {
                                        res= [];
                                        response.forEach(function(element) {
                                            if(element.Title.indexOf(criteria.Title) > -1)
                                                res.push(element);
                                        }, this);
                                    }
                                    else res = response;                                    

                                    data.resolve(res);
                                });
                            return data.promise();
                        },       

@generic11
Copy link

Just wanted to say thanks to dewelloper and tabalinas. Finally got filtering working with my js-grid.

@sharepointmike
Copy link

@dewelloper Json does throw on error on indexOf. I have all my "fields" directly under response.results.
How can I get my filtering working?

@htkcodes
Copy link

htkcodes commented Mar 25, 2018

@sharepointmike

IF YOUR RESULT Is EXPECTING A NUMBER DO

if(criteria.<fieldname> !== undefined)
loadData: function (filter) {
                            criteria = filter;
                            var data = $.Deferred();
                            $.ajax({
                                type: "GET",
                                contentType: "application/json; charset=utf-8",
                                url: "/fapplications",
                                dataType: "json"
                                }).done(function(response){
                                    var res = [];
                                    if(criteria.Name !== "")
                                    {
                                        response.forEach(function(element) {
//Name of your field should be here
//eg. if you have a field called email_id,you would put element.email_id.indexOf(criteria.email_id)>-1 ...
//do this for all your fields
//the indexof error should disappear.
                                            if(element.Name.indexOf(criteria.Name) > -1){
                                                res.push(element);
                                                response = res;
                                            }
                                        }, this);
                                    }
                                    else res = response;
                                    if(criteria.Title !== "")
                                    {
                                        res= [];
                                        response.forEach(function(element) {
                                            if(element.Title.indexOf(criteria.Title) > -1)
                                                res.push(element);
                                        }, this);
                                    }
                                    else res = response;                                    

                                    data.resolve(res);
                                });
                            return data.promise();
                        }, ```

@sharepointmike
Copy link

Thanks a lot!

@sharepointmike
Copy link

sharepointmike commented Mar 26, 2018

I got is almost working. I still get the error on a number field;

if(element.IDField.indexOf(criteria.IDField) > -1)

In this case element.IDField is 120893 Then I get the IndexOf error (object does not support)

Solved that by using:

if((element.IDField.toString()).indexOf(criteria.IDField) > -1)

@ellemaker
Copy link

ellemaker commented Apr 10, 2018

hi can anyone help me in filtering here's my code

screenshot_7
screenshot_6
screenshot_5

@PRIYANK014
Copy link

@htkcodes I'm getting the filtered response but grid is still showing all records.

@rohitoza147
Copy link

in DB file that code but filtter not work...
(function()
{

var db = {

   
					loadData: function(filter) 
					{
					 var db = $.Deferred();
					   return $.ajax({
					        type: "GET",
					        url: "get.php",
					        dataType: "json"
					    }).done(function(result) 
						{
					        result = $.grep(result, function(item) {
					             // some client-side filtering below
					               return filter.pname || item.pname === filter.pname;
			                       return filter.amount || item.amount === filter.amount;
     
					        });
					        db.resolve(result);
					    });
					    return db.promise();
					}
					

};

window.db = db;

}());

@wonsuc
Copy link

wonsuc commented Aug 16, 2018

I think loadData([filter]) function must have two parameter loadData([filter], useBuffer).

So the useBuffer is a boolean which determine the loadData function should load data from external source or current loaded buffer.

Then we can trigger client-side filtering like this,

// search with custom filter
var useBuffer = true;
$("#grid").jsGrid("search", { Name: "John" }, userBuffer).done(function() {
    console.log("filtering completed");
});

I know this is not ideal, but there should be an alternative way that prevents developers from being confused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests