I am new to jayData and am trying to filter on an entity set. The filter needs to perform an complex evaluation beyond what I saw in the samples.
Here is a working sample of what I am trying to accomplish (the listView line isn't and is just there to show what I plan to do with the data):
function () {
var weekday = moment().isoWeekday()-1;
console.log(weekday);
var de = leagueDB.DailyEvents.toArray(function (events) {
console.log(events);
var filtered = [];
for (var e = 0; e < events.length;e++) {
console.log(events[e]);
console.log(events[e].RecurrenceRule);
var rule = RRule.fromString(events[e].RecurrenceRule);
var ruleOptions = rule.options.byweekday;
var isDay = ruleOptions.indexOf(weekday);
console.log(ruleOptions, isDay);
if(isDay =! -1)
{
filtered.push(events[e]);
}
}
$("#listView").kendoListView({dataSource:filtered});
});
Basically it is just evaluating a recurring rule string to see if the current day meets that criteria, if so add that event to the list for viewing.
But it blows up when I try to do this:
eventListLocal:leagueDB.DailyEvents.filter(function(e){
console.log("The Weekday is:"+viewModel.weekday);
console.log(e);
console.log("The recurrence rule is:"+e.RecurrenceRule);
var rruleOptions = viewModel.rruleOptions(e.RecurrenceRule);
if (rruleOptions !== -1) {
return true;
}
}).asKendoDataSource()
The error that is generating is:
Exception: Unable to resolve type:undefined
The thing is it seems to be occurring on "e" and the console logs like the event is not being passed in. However, I am not seeing a list either. In short I am really confused as to what is going on.
Any help would be appreciated.
Thanks,
You can't write filter expressions such as this.
When you write .filter(...), jaydata will parse your expression and then it will generate filter for underlying provider, for example where for webSql and $filter for oDataProvider.
Both JayData expression parser and the data provider itself should understand your filter.
Your filter is not suitable for this approach, because most of your codes are not familiar for jaydata expression parser and the underlying data provider, for example your console.log etc.
You can simplify your filter, or you should load all your data into an array, and then you can use filter method of array itself, there, you can write any filter you like, and your filter will work. Of course this has performance issue in some scenarios when your data set is large.
Read more on http://jaydata.org/tutorials/entityexpressions-the-heart-of-jaydata
Related
Our VS-2022 development project is Blazor WASM Core-6 with local REST-API for data. Using Postman, my testing is not getting data from the controller call to a repository function -- using breakpoints and local debugging -- as one would expect.
The repository function return statement is return Ok(vehicleTrips);. The IEnumerable vehicleTrips data variable contains the correct four records as expected from the DB fetch.
From the controller the call to the repository function is:
var result = (await motripRepository.GetMOTripsByDateRange((int)eModelType.Vehicle, pVehicleList, pDateFrom, pDateTo)!)!;
The controller function signature is:
[HttpGet("byDateRange/{pVehicleList}/{pDateFrom}/{pDateTo}")]
[ActionName(nameof(GetVehicleMOTripsByDateRange))]
public async Task<ActionResult<IEnumerable<MOTRIP>>> GetVehicleMOTripsByDateRange([FromRoute] string pVehicleList, [FromRoute] string pDateFrom, [FromRoute] string pDateTo) {
This is my problem. The result return value from the repository has a return.Value of null -- NOT four trip records as we should.
Additionally, the VS-Studio's 'local'-debugger shows that there are other properties of return such as .Return and .Return.Value.Count as 4 (four).
My question is "what could be causing this"? All of my other rest-api calls and controller calls with Postman work correctly as one would expect.
Did I select the wrong type of "controller" from Visual-Studio? I am not experienced at all in coding classic MVC web-applications. VS-Blazor offer a number of controller-types. In the past, I "copied" a working controller and "changed the code" for a different "model".
Your assistance is welcome and appreciated. Thanks...John
I found out what actually happened to cause the result.Value is null and had nothing to do with the controller-type -- it was in the interpretation of the return value from the repository function.
I found an SO link Get a Value from ActionResult<object> in a ASP.Net Core API Method that explains how to respond to a ActionResult<objecttype> return value in the reply/answer section with the word "actual" is first defined. You will see this word "actual" in my revised code below.
My revised code is posted here with comments both inside the code section and below the code section. My comment inside the code begins with "<==" with text following until "==>"
// Initialize.
MOTRIP emptyMoTrip = new MOTRIP();
MOTRIP? resultMoTrip = new MOTRIP();
IEnumerable<MOTRIP> allTrips = Enumerable.Empty<MOTRIP>();
int daysPrevious = (int)(pTripType == eTripType.Any ? eDateRangeOffset.Week : eDateRangeOffset.Month);
// convert DateRangeOffset to 'dateonly' values.
DateOnly dtTo = DateOnly.FromDateTime( DateTime.Today);
DateOnly dtFrom = dtTo.AddDays(daysPrevious);
// Fetch the vehicle trips by date-range.
var result = await GetVehicleMOTripsByDateRange(UID_Vehicle.ToString(), dtFrom.ToString(), dtTo.ToString());
if ((result.Result as OkObjectResult) is null) { **<== this is the fix from the SO link.==>**
return StatusCode(204, emptyMoTrip);
}
var statusCode = (result.Result as OkObjectResult)!.StatusCode;
if (statusCode==204) {
return StatusCode(204, emptyMoTrip);
}
**<== this next section allows code to get the result's DATA for further processing.==>**
var actual = (result.Result as OkObjectResult)!.Value as IEnumerable<MOTRIP>;
allTrips = (IEnumerable<MOTRIP>)actual!;
if ((allTrips is not null) && (!allTrips.Any())) {
return StatusCode(204, emptyMoTrip);
}
<== this next section continues with business-logic related to the result-DATA.==>
if (allTrips is not null && allTrips.Any()) {
switch (blah-blah-blah) {
**<== the remainder of business logic is not shown as irrelevant to the "fix".==>**
Please use browser search for "<==" to find my code-comments.
Please use browser search for "actual" and "OkObjectResult" to see the relevant code fix sentences.
I am updating sort & filter models via api:
this.gridApi.setFilterModel(filterModels);
this.gridApi.setSortModel(sortModels);
The problem with this is I have a server request bound to the change even of both sort & filter so when user changes then the data is updated. This means when I change model on code like restoring a state or resetting the filters it causes multiple requests.
Is there a way to update the filter/sort model without triggering the event?
I see there is a ColumnEventType parameter but couldn't see how it works. Can I specify some variable that I can look for inside my event handlers to get them to ignore calls that are not generated from user?
I am trying to manage URL state so when url query params change my code sets the models in the grids but this ends up causing the page to reload multiple times because the onFilter and onSort events get called when the model is set and there is no way I can conceive to prevent this.
At the time, you are going to have to manage this yourself, ie, just before you call the setModel, somehow flag this in a shared part of your app (maybe a global variable)
Then when you react to these events, check the estate of this, to guess where it came from.
Note that at the moment, we have added source to the column events, but they are not yet for the model events, we are planning to add them though, but we have no ETA
Hope this helps
I had to solve similar issue. I found solution which working for my kind of situation. Maybe this help someone.
for (let j = 0; j < orders.length; j++) {
const sortModelEntry = orders[j];
if (typeof sortModelEntry.property === 'string') {
const column: Column = this.gridColumnApi.getColumn(sortModelEntry.property);
if (column && ! column.getColDef().suppressSorting) {
column.setSort(sortModelEntry.direction.toLowerCase());
column.setSortedAt(j);
}
}
this.gridApi.refreshHeader();
Where orders is array of key-value object where key is name of column and value is sorting directive (asc/desc).
Set filter without refresh was complicated
for (let j = 0; j < filters.length; j++) {
const filterModelEntry = filters[j];
if (typeof filterModelEntry.property === 'string') {
const column: Column = this.gridColumnApi.getColumn(filterModelEntry.property);
if (column && ! column.getColDef().suppressFilter) {
const filter: any = this.gridApi.getFilterApi(filterModelEntry.property);
filter['filter'] = filterModelEntry.command;
filter['defaultFilter'] = filterModelEntry.command;
filter['eTypeSelector'].value = filterModelEntry.command;
filter['filterValue'] = filterModelEntry.value;
filter['filterText'] = filterModelEntry.value;
filter['eFilterTextField'].value = filterModelEntry.value;
column.setFilterActive(true);
}
}
}
Attributes in filter:
property - name of column
command - filter action (contains, equals, ...)
value - value used in filter
For anyone else looking for a solution to this issue in Nov 2020, tapping into onFilterModified() might help. This gets called before onFilterChanged() so setting a value here (eg. hasUserManuallyChangedTheFilters = false, etc.) and checking the same in the filter changed event is a possible workaround. Although, I haven't found anything similar for onSortChanged() event, one that gets called before the sorting is applied to the grid.
I am not sure any clean way to achieve this but I noticed that FilterChangedEvent has "afterFloatingFilter = false" only if filterModel was updated from ui.
my workaround is as below
onFilterChanged = event:FilterChangedEvent) => {
if(event.afterFloatingFilter === undefined) return;
console.log("SaveFilterModel")
}
I've read all the documentation I can find and watched all the videos I can find and don't understand how to do this. I have set up an xPages REST Service and it works well. Now I want to place the results of the service into either a combobox or typeahead text field. Ideally I would like to know how to do it for both types of fields.
I have an application which has a view containing a list of countries, another view containing a list of states, and another containing a list of cities. I would like the first field to only display the countries field from the list of data it returns in the XPages REST Service. Then, depending upon which country was selected, I would like the states for that country to be listed in another field for selection, etc.
I can see code for calling the REST Service results from a button, or from a dojo grid, but I cannot find how to call it to populate either of the types of fields identified above.
Where would I call the Service for the field? I had thought it would go in the Data area, but perhaps I've just not found the right syntax to use.
November 6, 2017:
I have been following your suggestion, but am still lost as can be. Here's what I currently have in my code:
x$( "#{id:ApplCountry}" ).select2({
placeholder: "select a country",
minimumInputLength: 2,
allowClear : true,
multiple: false,
ajax: {
dataType: 'text/plain',
url: "./Application.xsp/gridData",
quietMillis: 250,
data: function (params) {
return {
search:'[name=]*'+params.term+'*',
page: params.page
};
},
processResults: function (data, page) {
var data = $.map(data, function (obj) {
obj.id = obj.id || obj["#entityid"];
obj.text = obj.text || obj.name;
return obj;
});
},
return {results: data};
}
}
});
I'm using the dataType of 'text/plain' because that was what I understood I should use when gathering data from a domino application. I have tried changing this to json but it makes no difference.
I'm using processResults because I understand this is what should be used in version 4 of select2.
I don't understand the whole use of the hidden field, so I've stayed away from that.
No matter what I do, although my REST service works if I put it directly in the url, I cannot get any data to display in the field. All I want to display in the field is the country code of the document, which is in the field named "name" (not my choice, it's how it came before I imported the data from MySQL.
I have read documentation and watched videos, but still don't really understand how everything fits together. That was my problem with the REST service. If you use it in Dojo, you just put the name of the service in a field on the Dojo element and it's done, so I don't understand why all the additional coding for another type of domino element. Shouldn't it work the same way?
I should point out that at some points it does display the default message, so it does find the field. Just doesn't display the country selections.
I think the issue may be that you are not returning SelectItems to your select2, and that is what it is expecting. When I do something like you are trying, I actually use a bean to generate the selection choices. You may want to try that or I'm putting in the working part of my bean below.
The Utils.getItemValueAsString is a method I use to return either the string value of a field, or if it is not on the document/empty/null an empty string. I took out an if that doesn't relate to this, so there my be a mismatch, but I hope not.
You might be able to jump directly to populating the arrayList, but as I recall I needed to leverage the LinkedHashMap for something.
You should be able to do the same using SSJS, but since that renders to Java before executing, I find this more efficient.
For label/value pairs:
LinkedHashMap lhmap = new LinkedHashMap();
Document doc = null;
Document tmpDoc = null;
allObjects.addElement(doc);
if (dc.getCount() > 0) {
doc = dc.getFirstDocument();
while (doc != null) {
lhmap.put(Utils.getItemValueAsString(doc, LabelField, true), Utils.getItemValueAsString(doc, ValueField, true));
}
tmpDoc = dc.getNextDocument(doc);
doc.recycle();
doc = tmpDoc;
}
}
List<SelectItem> options = new ArrayList<SelectItem>();
Set set = lhmap.entrySet();
Iterator hsItr = set.iterator();
while (hsItr.hasNext()) {
Map.Entry me = (Map.Entry) hsItr.next();
// System.out.println("after: " + hStr);
SelectItem option = new SelectItem();
option.setLabel(me.getKey() + "");
option.setValue(me.getValue() + "");
options.add(option);
}
System.out.println("About to return from generating");
return options;
}
I ended up using straight up SSJS. Worked like a charm - very simple.
I am writing a protractor test case to compare the name(s) of the displayed data is same as the searched name.
Even though my test case works fine, I am not able to understand what is happening. Because when i expect the name to compare, it compares as expected, but when i print the elementFinder's(rowData)(i have attached the output screen shot here) value in console.log, it show a huge list of some values which i am not able to understand?
PS: I am a newbie to protractor`
This is the testCase:
it('should show proper data for given last name', function () {
var searchValue='manning';
searchBox.sendKeys(searchValue);
search.click();
element.all(by.binding('row.loanNumber')).count().then(function(value) {
var loanCount = value;
for (var i = 0; i < loanCount; i++) {
var rowData = element.all(by.binding('row.borrowerName')).get(i).getText();
expect(rowData).toMatch(searchValue.toUpperCase());
console.log(rowData,'*****',searchValue.toUpperCase());
}
});
});`
And give me valuable suggestions about my style of code
rowData is a promise (not a value), so when you console.log it, you get the promise object
Protractor patches Jasmine to automatically resolve promises within the expect(), so that's how it knows to resolve the value and compare to the expected result.
If you want to console.log the value, you need to resolve the promise with .then() to get the value.
rowData.then(function(rowDataText) {
console.log(rowDataText);
)}
This is pretty much everyone's first question when they start using protractor. You will want to learn how promises work if you want a good understanding of how to manipulate them.
I have a publication, essentially what's below:
Meteor.publish('entity-filings', function publishFunction(cik, queryArray, limit) {
if (!cik || !filingsArray)
console.error('PUBLICATION PROBLEM');
var limit = 40;
var entityFilingsSelector = {};
if (filingsArray.indexOf('all-entity-filings') > -1)
entityFilingsSelector = {ct: 'filing',cik: cik};
else
entityFilingsSelector = {ct:'filing', cik: cik, formNumber: { $in: filingsArray} };
return SB.Content.find(entityFilingsSelector, {
limit: limit
});
});
I'm having trouble with the filingsArray part. filingsArray is an array of regexes for the Mongo $in query. I can hardcode filingsArray in the publication as [/8-K/], and that returns the correct results. But I can't get the query to work properly when I pass the array from the router. See the debugged contents of the array in the image below. The second and third images are the client/server debug contents indicating same content on both client and server, and also identical to when I hardcode the array in the query.
My question is: what am I missing? Why won't my query work, or what are some likely reasons it isn't working?
In that first screenshot, that's a string that looks like a regex literal, not an actual RegExp object. So {$in: ["/8-K/"]} will only match literally "/8-K/", which is not the same as {$in: [/8-K/]}.
Regexes are not EJSON-able objects, so you won't be able to send them over the wire as publish function arguments or method arguments or method return values. I'd recommend sending a string, then inside the publish function, use new RegExp(...) to construct a regex object.
If you're comfortable adding new methods on the RegExp prototype, you could try making RegExp an EJSON-able type, by putting this in your server and client code:
RegExp.prototype.toJSONValue = function () {
return this.source;
};
RegExp.prototype.typeName = function () {
return "regex";
}
EJSON.addType("regex", function (str) {
return new RegExp(str);
});
After doing this, you should be able to use regexes as publish function arguments, method arguments and method return values. See this meteorpad.
/8-K/.. that's a weird regex. Try /8\-K/.
A minus (-) sign is a range indicator and usually used inside square brackets. The reason why it's weird because how could you even calculate a range between 8 and K? If you do not escape that, it probably wouldn't be used to match anything (thus your query would not work). Sometimes, it does work though. Better safe than never.
/8\-K/ matches the string "8-K" anywhere once.. which I assume you are trying to do.
Also it would help if you would ensure your publication would always return something.. here's a good area where you could fail:
if (!cik || !filingsArray)
console.error('PUBLICATION PROBLEM');
If those parameters aren't filled, console.log is probably not the best way to handle it. A better way:
if (!cik || !filingsArray) {
throw "entity-filings: Publication problem.";
return false;
} else {
// .. the rest of your publication
}
This makes sure that the client does not wait unnecessarily long for publications statuses as you have successfully ensured that in any (input) case you returned either false or a Cursor and nothing in between (like surprise undefineds, unfilled Cursors, other garbage data.