Announcement
Collapse
No announcement yet.
X
-
Hi danaconway ,
sorry, my code from #2 has a obvious error. It should be like this:
Code:const criteria = filterBuilder.getCriteria(); if (!listGrid.willFetchData(criteria)) { listGrid.filterData(criteria); // Added line, we know it is synchronous because of the "if" above myMethod(); } else { listGrid.filterData(criteria, function(dsResponse, data, dsRequest) { myMethod(); }); }
Blama
Leave a comment:
-
Thanks for the test case, but you'll need to clarify precisely what you're doing, what you're seeing and what you expect.
Specifically, you have a DS field declared of type "datetime" in which you've provided String values, not Date instances, so that won't work at all. So what criteria are you specifically trying?
Did you check your Developer Console for warnings and JS errors?
How are you checking whether your callback is called? Please check by logging a warning rather than, e.g., just seeing if the final result is as expected - which may not occur due to other bugs in your code.
Leave a comment:
-
I do appreciate the responses, but the code in post #2 from Blama does not work in my test case. I am posting the code below. Perhaps it will give some insight into what I am doing incorrectly.
Code:const testData = [ {"id":55,"desc":" ","r":5621,"m":13,"p":22,"time":"02:09:35"}, {"id":2,"desc":"TUV","r":2790,"m":1,"p":1111,"time":"23:50:06"}, {"id":45,"desc":" ","r":17819,"m":1,"p":1144,"time":"02:49:18"}, {"id":1,"desc":" ","r":1000,"m":1,"p":909,"time":"22:39:15"}, {"id":49,"desc":" ","r":4129,"m":1,"p":1052,"time":"02:08:34"}, {"id":24,"desc":" ","r":6168,"m":1,"p":1384,"time":"02:48:26"}, {"id":22,"desc":" ","r":11764,"m":1,"p":1045,"time":"02:49:20"}, {"id":27,"desc":" ","r":2199,"m":1,"p":680,"time":"02:49:20"}, {"id":21,"desc":" ","r":12129,"m":1,"p":376,"time":"02:48:25"}, {"id":19,"desc":" ","r":4917,"m":1,"p":788,"time":"02:49:21"}, {"id":53,"desc":" ","r":16384,"m":1,"p":697,"time":"02:48:54"}, {"id":51,"desc":" ","r":7911,"m":13,"p":39,"time":"01:44:11"}, {"id":44,"desc":" ","r":18245,"m":1,"p":639,"time":"02:33:12"}, {"id":52,"desc":" ","r":6090,"m":1,"p":575,"time":"01:40:03"}, {"id":29,"desc":" ","r":2402,"m":1,"p":904,"time":"02:09:53"}, {"id":32,"desc":" ","r":14600,"m":1,"p":1257,"time":"02:17:13"}, {"id":25,"desc":" ","r":10776,"m":13,"p":10,"time":"02:49:19"}, {"id":11,"desc":"XYZ","r":2880,"m":1,"p":1144,"time":"23:58:54"}, {"id":57,"desc":" ","r":5260,"m":13,"p":21,"time":"02:15:24"}, {"id":35,"desc":" ","r":1589,"m":1,"p":655,"time":"02:49:20"}, {"id":42,"desc":" ","r":3286,"m":13,"p":33,"time":"02:22:48"}, {"id":50,"desc":" ","r":10322,"m":1,"p":1352,"time":"01:38:42"}, {"id":50,"desc":" ","r":10322,"m":1,"p":1352,"time":"01:38:42"}, {"id":30,"desc":" ","r":15278,"m":1,"p":1311,"time":"02:49:20"}, {"id":28,"desc":" ","r":2004,"m":1,"p":441,"time":"02:15:14"}, {"id":23,"desc":" ","r":5305,"m":13,"p":84,"time":"02:03:38"}, {"id":31,"desc":" ","r":851,"m":1,"p":715,"time":"02:49:19"}, {"id":26,"desc":" ","r":1639,"m":1,"p":210,"time":"02:49:20"}, {"id":54,"desc":" ","r":16384,"m":1,"p":697,"time":"02:01:56"}, {"id":47,"desc":" ","r":16317,"m":13,"p":35,"time":"02:41:54"}, {"id":9,"desc":" ","r":2800,"m":1,"p":909,"time":"23:59:57"}, {"id":43,"desc":" ","r":14695,"m":1,"p":439,"time":"02:49:20"}, {"id":4,"desc":"FGH","r":2840,"m":1,"p":1111,"time":"23:29:04"}, {"id":37,"desc":" ","r":4349,"m":1,"p":1316,"time":"02:49:19"}, {"id":3,"desc":"XYZ","r":2810,"m":1,"p":1111,"time":"22:51:52"}, {"id":7,"desc":" ","r":2860,"m":1,"p":766,"time":"22:51:31"}, {"id":15,"desc":"PQR","r":2830,"m":1,"p":766,"time":"23:29:04"}, {"id":41,"desc":" ","r":15489,"m":1,"p":1049,"time":"02:48:55"}, {"id":18,"desc":" ","r":2830,"m":1,"p":766,"time":"12:08:42"}, {"id":13,"desc":" ","r":2810,"m":1,"p":1111,"time":"08:55:33"}, {"id":48,"desc":" ","r":16384,"m":1,"p":697,"time":"01:35:09"}, {"id":5,"desc":"XYZ","r":2870,"m":1,"p":766,"time":"22:52:10"}, {"id":6,"desc":"PQR","r":2830,"m":1,"p":766,"time":"23:59:57"}, {"id":20,"desc":" ","r":10926,"m":1,"p":810,"time":"02:49:20"}, {"id":16,"desc":" ","r":2804,"m":12,"p":35,"time":"11:10:04"}, {"id":56,"desc":" ","r":5621,"m":6,"p":134,"time":"02:12:27"}, {"id":12,"desc":" ","r":2810,"m":1,"p":1111,"time":"22:44:15"}, {"id":36,"desc":" ","r":16574,"m":1,"p":295,"time":"02:49:06"}, {"id":33,"desc":" ","r":4455,"m":1,"p":702,"time":"02:45:17"} ]; // Define variables to be used later; let gridFilter, mapFilterForm, myListGrid; // Define the client only data source for the grid let myListGridDS = isc.DataSource.create({ ID: "myListGridDS", fields: [ {name: "id", type: "integer", primaryKey: true}, {name: "desc", type: "text"}, {name: "r", type: "float"}, {name: "m", type: "integer"}, {name: "p", type: "float"}, {name: "time", type: "datetime", timeUnitOptions: ["hour", "minute", "second"]} ], dataFormat: "json", clientOnly: true }); // Create the layout to include a filter builder and a list grid isc.VLayout.create({ width: "100%", height: "100%", padding: 5, members: [ isc.VLayout.create({ width: "100%", height: "15%", padding: 0, members: [ // Filter for grid gridFilter = isc.FilterBuilder.create({ ID:"gridFilter", dataSource: "myListGridDS", width: "98%", height: "10%", fieldPickerWidth: 120, operatorPickerWidth: 120, valueItemWidth: 100, padding: 5 }), isc.HLayout.create({ width: "100%", height: 35, members: [ mapFilterForm = isc.DynamicForm.create({ numCols: 4, fields: [ {name: "applyToMap", title: "Apply to map", type: "checkbox", redrawOnChange: true, width: 100, defaultValue: false}, {name: "hideUnmatched", title: "Hide unmatched", type: "checkbox", width: 100, defaultValue: false, showIf: "form.getValue('applyToMap') === true "} ] }), isc.LayoutSpacer.create({ width: "30%" }), isc.IButton.create({ ID: "gridFilterButton", title: "Apply Filter", height: 30, width: 120, click: function(){ const criteria = gridFilter.getCriteria(); // TODO: This works in the sense of the list grid is guaranteed to be filtered // each time. However, the callback doesn't get fired so I don't know when to // call checkMapFilter() // //myListGrid.filterData(criteria, function(dsResponse, data, dsRequest) { // checkMapFilter(); //}); // TODO: This doesn't seem to work. Technically, there is no server call since // we are using client only data, so we fall into the first condition and filterData() // never gets called. if( !myListGrid.willFetchData(criteria) ) { checkMapFilter(); } else { myListGrid.filterData(criteria, function(dsResponse, data, dsRequest) { checkMapFilter(); }); } } }), isc.LayoutSpacer.create({ width: 5 }), isc.IButton.create({ ID: "clearFilterButton", title: "Clear Filter", height: 30, width: 120, click: function(){ myListGrid.clearCriteria(); // Notify map controller to clear filtering // clearMapFilters(); } }) ] }) ] }), myListGrid = isc.ListGrid.create({ ID: "myListGrid", width: "100%", height: "*", alternateRecordStyles: true, dataSource: "myListGridDS", autoFetchData: true, emptyMessage: "No data available", canFreezeFields: true, selectionType: "multiple", cellHeight: 30, wrapCells: true, primaryKey: "id", fields: [ {name: "id", title: "ID", width: 70, align: "center", frozen: true, canHide: false}, {name: "desc", title: "Name", align: "center"}, {name: "r", title: "R", align: "center"}, {name: "p", title: "P", align: "center"}, {name: "m", title: "M", align: "center"}, {name: "time", title: "Time", align: "center"} ], sortField: "id", sortDirection: "ascending" }) ] }); // Set the initial cache data myListGridDS.setCacheData(testData); // This should be called AFTER myListGrid.filterData() is complete function checkMapFilter() { // Check to see if we need to apply this filtering to the map let applyToMap = mapFilterForm.getField("applyToMap").getValue(); if( applyToMap ) { // Check to see if the user wants to hide the unmatched items let hideOthers = mapFilterForm.getField("hideUnmatched").getValue(); // Notify map controller that we need to filter the map and send applyToMap and hideOthers values // setMapFilters(applyToMap, hideOthers); } else { // If apply to map gets unchecked, make sure we clear any previous filters // clearMapFilters(); } }
Leave a comment:
-
Just to make it official - Blama's post #2 contains correct code for taking action once filtering completes. This is also the approach that is documented.
You don't want to set useClientFiltering:false because client filtering is a huge performance and responsiveness boost.
You don't want to call setData() after filterData() because, as you've discovered, this breaks automatic filtering (including breaking the filterEditor, if used).
So again the right approach is just to do what's doc'd, and post #2 here shows correct code for this.
Leave a comment:
-
Hi @danaconway,
I think that one of the two ways should work and is the correct approach. But that’s for Isomorphic to confirm.
If you can’t get the handler called without your workaround I think that’s an issue.
Can you show a test case? Should be easy as it is already a clientOnly DataSource.
Best regards
Blama
Leave a comment:
-
It seems that I could work around the issue by doing this:
Code:const criteria = filterBuilder.getCriteria(); dataSource.filterData(criteria, function(dsResponse, data, dsRequest) { listGrid.setData(data); myFilterFunction(data); });
Leave a comment:
-
Hi Blama ,
I have tried your suggestions, but have not had any luck. I need a way to know when the filterData operation is complete. I have not had any trouble with any other methods that provide a callback optional parameter. For instance, I have used a callback successfully when calling addData or updateData on my DataSource, e.g.
Code:dataSource.addData(newData, filterCallback);
One thing that is not completely clear is that when I want to add/update/delete the data in my grid, I operate on the underlying DataSource. However, from the examples, it seems that you operate on the ListGrid itself for filtering purposes and not the DataSource. Or, am I wrong and should I be operating on the DataSource for filtering purposes in this case?
Leave a comment:
-
Alternatively to willFetchData() this, try this in your ListGrid properties:
Code:dataProperties: { useClientFiltering: false }
Best regards
Blama
Leave a comment:
-
Hi danaconway,
if the way I see it is correct, it is like this: "No entry in RPC Manager Tab of Developer Console" = "No CallBack executed".
And if all data is local, you'll only get the 1st fetch in the ListGrid and then everything else is synchronous. Therefore you need willFetchData().
Best regards
Blama
Leave a comment:
-
Hi Blama,
Thank you for your response. I guess what I'm saying is that since I'm using a clientOnly DataSource, there is technically no server contact. This DataSource gets updated by data coming over a websocket. When I click the "Apply Filter" button, the filter operation is only working on the cached client data. The RPC tab shows nothing nor do I get any errors. However, the filterData function is still asynchronous and I need a way to know when the operation is complete. I thought I'd be able to use the callback, but it's just not firing.
Dana
Leave a comment:
-
Hi danaconway,
are you saying that the callback does not fire even though there was a server contact? Did you check the Developer Console RPC Tab for the contact, the normal Console for error messages?
If that's all OK, I'd say the code should look like this:
Code:const criteria = filterBuilder.getCriteria(); if (!listGrid.willFetchData(criteria)) { myMethod(); } else { listGrid.filterData(criteria, function(dsResponse, data, dsRequest) { myMethod(); }); }
I don't think you'll need or want invalidateCache().
Best regards
BlamaLast edited by Blama; 8 Nov 2021, 13:35.
Leave a comment:
-
ListGrid.filterData() callback question
I'm using SmartClient_v121p_2020-04-14_PowerEdition. I have a ListGrid backed by a "clientOnly" DataSource. I also have a FilterBuilder component that is used to filter the ListGrid. After the user enters the desired criteria and clicks my "Apply Filter" button, I filter the ListGrid as such:
Code:const criteria = filterBuilder.getCriteria(); listGrid.filterData(criteria);
callback (optional) - type: DSCallback
callback to invoke when a fetch is complete. Fires only if server contact was required; see fetchData() for details
Code:listGrid.filterData(criteria, function(dsResponse, data, dsRequest) { // DO SOMETHING HERE });
Changes to criteria may or may not result in a DSRequest to the server due to client-side filtering. You can call willFetchData(criteria) to determine if new criteria will result in a server fetch.
If you need to force data to be re-fetched, you can call invalidateCache() and new data will automatically be fetched from the server using the current criteria and sort direction. NOTE: when using invalidateCache() there is no need to also call fetchData() and in fact this could produce unexpected results.
Tags: None
Leave a comment: