How to Remove the addPreSearch Filter - dynamics-crm-2011

I am trying to remove the PreSearch filer and my code is as below. How can I achieve the same?
Xrm.Page.getControl("productid").removePreSearch(function () {
Object
});
Xrm.Page.getControl("productid").addPreSearch(function () {
fetchxml2();
});
function fetchxml2() {
var fetchXml1 = "<filter type='and'>"
fetchXml1 += "<condition attribute='productid' operator='in' >";
for (var i = 0; i < Itemid.length; i++) {
fetchXml1 += "<value>" + Itemid[i] + "</value>";
}
fetchXml1 += "</condition>";
fetchXml1 += "</filter>";
Xrm.Page.getControl("productid").addCustomFilter(fetchXml1);
//Xrm.Page.getControl("productid").removePreSearch(fetchXml1);
};

In order to be able to remove the handler via removePreSearch, avoid using an anonymous function by creating a named function and using that in both addPreSearch and removePreSearch:
function preSearchHandler(){
fetchxml2();
}
Xrm.Page.getControl("productid").removePreSearch(preSearchHandler);
Xrm.Page.getControl("productid").addPreSearch(preSearchHandler);

Just wanted to add this to the discussion:
If you, say, have three different custom filters on a lookup field, the functionality will stack when you apply a new filter.
For example, if you have an option set that calls addPreSearch() on the field, if you select all three different options, you will have all three filters applied to the field simultaneously.
say the option set has three options of [option A, option B, option C],
the corresponding functions are, for simplicity [filterA, filterB, filterC],
on the change event of the option set, for each filter that you apply, simply remove the other two (in this case).
if (optionSet == 810500000) {//option A
Xrm.Page.getControl('lookup').addPreSearch(filterA);
Xrm.Page.getControl('lookup').removePreSearch(filterB);
Xrm.Page.getControl('lookup').removePreSearch(filterC);
}
else if (optionSet == 810500001) {//option B
Xrm.Page.getControl('lookup').addPreSearch(filterB);
Xrm.Page.getControl('lookup').removePreSearch(filterA);
Xrm.Page.getControl('lookup').removePreSearch(filterC);
}//so on and so forth
I hope this helps someone out, I was able to apply custom filters to a lookup based on four distinct selections and remove the "stackable" filters by addition and removal in this manner. It's a little ugly, but, hey, it works. At the end of the day, sometimes the most elegant solution is to just win, win win win win.
If you need more context (fetchXml) and such, I can post that, too...but it doesn't really go along with the point I was trying to make. These filters can be applied simultaneously! That's the main idea I wanted to convey here.

Related

How to power a windowed virtual list with cursor based pagination?

Take a windowed virtual list with the capability of loading an arbitrary range of rows at any point in the list, such as in this following example.
The virtual list provides a callback that is called anytime the user scrolls to some rows that have not been fetched from the backend yet, and provides the start and stop indexes, so that, in an offset based pagination endpoint, I can fetch the required items without fetching any unnecessary data.
const loadMoreItems = (startIndex, stopIndex) => {
fetch(`/items?offset=${startIndex}&limit=${stopIndex - startIndex}`);
}
I'd like to replace my offset based pagination with a cursor based one, but I can't figure out how to reproduce the above logic with it.
The main issue is that I feel like I will need to download all the items before startIndex in order to receive the cursor needed to fetch the items between startIndex and stopIndex.
What's the correct way to approach this?
After some investigation I found what seems to be the way MongoDB approaches the problem:
https://docs.mongodb.com/manual/reference/method/cursor.skip/#mongodb-method-cursor.skip
Obviously he same approach can be adopted by any other backend implementation.
They provide a skip method that allows to skip an arbitrary amount of items after the provided cursor.
This means my sample endpoint would look like the following:
/items?cursor=${cursor}&skip=${skip}&limit=${stopIndex - startIndex}
I then need to figure out the cursor and the skip values.
The following code could work to find the closest available cursor, given I store them together with the items:
// Limit our search only to items before startIndex
const fragment = items.slice(0, startIndex);
// Find the closest cursor index
const cursorIndex = fragment.length - 1 - fragment.reverse().findIndex(item => item.cursor != null);
// Get the cursor
const cursor = items[cursorIndex];
And of course, I also have a way to know the skip value:
const skip = items.length - 1 - cursorIndex;

Efficient way to determine if there is more than one distinct item using linq.js

I'm looking for an efficient way using linq.js to determine if a collection has more than one distinct value. I assume that the following approach is inefficient because it has to consider the entire collection.
if (Enumerable.From(collection).Distinct().Take(2).Count() > 1) {
//it's not unique, continue loop
}
My question is similar to one:
Efficient Linq Enumerable's 'Count() == 1' test
Is there a more efficient linq.js-based technique? Thanks!
If you're specifically testing to see if a collection has more than one item in it, the idiomatic way to write it (IMHO) is to use Skip in conjunction with Any. Skip the first item and if there are any others in the collection, it has more than one. If it was empty, the Skip would effectively do nothing and there still wouldn't be any other items in the collection.
In your case, your condition would be:
if (Enumerable.From(collection).Distinct().Skip(1).Any()) {
//it's not unique, continue loop
}
var test = collection[0];
if (Enumerable
.From(collection)
.Skip(1)
.Any(function (e) { return e != test; })
)
Let me explain it. At least 2 distinct items mean that for any item there is at least one item that is not equal to it. Let's pick first item, you could pick any other, just first is more convenient and let's see if there is any other number not equal to it (except itself).

How to maintain counters with LinqToObjects?

I have the following c# code:
private XElement BuildXmlBlob(string id, Part part, out int counter)
{
// return some unique xml particular to the parameters passed
// remember to increment the counter also before returning.
}
Which is called by:
var counter = 0;
result.AddRange(from rec in listOfRecordings
from par in rec.Parts
let id = GetId("mods", rec.CKey + par.UniqueId)
select BuildXmlBlob(id, par, counter));
Above code samples are symbolic of what I am trying to achieve.
According to the Eric Lippert, the out keyword and linq does not mix. OK fair enough but can someone help me refactor the above so it does work? A colleague at work mentioned accumulator and aggregate functions but I am novice to Linq and my google searches were bearing any real fruit so I thought I would ask here :).
To Clarify:
I am counting the number of parts I might have which could be any number of them each time the code is called. So every time the BuildXmlBlob() method is called, the resulting xml produced will have a unique element in there denoting the 'partNumber'.
So if the counter is currently on 7, that means we are processing 7th part so far!! That means XML returned from BuildXmlBlob() will have the counter value embedded in there somewhere. That's why I need it somehow to be passed and incremented every time the BuildXmlBlob() is called per run through.
If you want to keep this purely in LINQ and you need to maintain a running count for use within your queries, the cleanest way to do so would be to make use of the Select() overloads that includes the index in the query to get the current index.
In this case, it would be cleaner to do a query which collects the inputs first, then use the overload to do the projection.
var inputs =
from recording in listOfRecordings
from part in recording.Parts
select new
{
Id = GetId("mods", recording.CKey + part.UniqueId),
Part = part,
};
result.AddRange(inputs.Select((x, i) => BuildXmlBlob(x.Id, x.Part, i)));
Then you wouldn't need to use the out/ref parameter.
XElement BuildXmlBlob(string id, Part part, int counter)
{
// implementation
}
Below is what I managed to figure out on my own:.
result.AddRange(listOfRecordings.SelectMany(rec => rec.Parts, (rec, par) => new {rec, par})
.Select(#t => new
{
#t,
Id = GetStructMapItemId("mods", #t.rec.CKey + #t.par.UniqueId)
})
.Select((#t, i) => BuildPartsDmdSec(#t.Id, #t.#t.par, i)));
I used resharper to convert it into a method chain which constructed the basics for what I needed and then i simply tacked on the select statement right at the end.

How to search and sort with CouchDB in one map function

I'm stumbling a bit with my CouchDB knowledge.
I have a database of content that is tagged with an array of tags and has a created date.
I want to create a view that pulls a limited number of newest stories tagged with a specific tag.
For example, the newest 6 stories tagged "Business."
Ran across this question, which seems to get me almost to where I need to go, but I'm missing one key element, which I think is how to craft the query string to sort by one key while searching by the other.
Here's my map function.
function(doc) {
if (doc.published == "yes" && doc.type == "news") {
for (var i = 0; i < doc.tags.length; i++) {
if (doc.tags[i]) {
emit([doc.created, doc.tags[i]], doc);
}
}
}
}
So how do I query that view for a all documents tagged "Business" that are the newest documents based on created.
The created attribute is a date sortable format.
First, I would switch the order of your emit:
emit([doc.tags[i], doc.created]);
(leave out doc as well, you can just add include_docs=true to get the entire document, and your view won't take up so much disk-space in the process)
Now you can query for the all the stories tagged as "Business" by using the following querystring:
startkey=["Business"]&endkey=["Business",{}]
You'll get all the documents with the tag business, and they'll be sorted by date.
This takes advantage of view collation, which basically is the rules governing how indexes are sorted/queried. For complex keys like this, the sorting is done for each item of the array separately. (ie. the first key is sorted first, the second key is sorted second, etc) This is why the order matters, as you must always move from left to right when querying a view index.
If you want the 6 most recent, your querystring will need to change:
descending=true&limit=6&endkey=["Business"]&startkey=["Business",{}]
NOTICE You need to swap the startkey/endkey values, due to how the descending parameter works. See the View reference page on the wiki for further explanation.
OK, I think I figured this out, but I'm not quite certain I fully understand it.
I found this story about complex keys and searching and sorting.
My map function looks like this:
function(doc) {
if (doc.published == "yes" && doc.type == "news") {
for (var i = 0; i < doc.tags.length; i++) {
if (doc.tags[i]) {
emit([doc.tags[i], doc.created], doc);
}
}
}
}
And to query and sort using it, the query looks like this.
http://localhost:5984/database/_design/story/_view/tagged?limit=10&startkey=["Business"]&endkey=["Business",{}]&descending=false
I'm getting the results I want, but I'm not entirely certain I understand it all.

YUI Column Selection

I'm having issues using YUI's DataTable Column Selection Functionality. I've tried,
myEndColDataTable.subscribe("theadCellClickEvent", myEndColDataTable.onEventSelectColumn);
and
myEndColDataTable.subscribe("cellClickEvent", function (oArgs) {
this.selectColumn(this.getColumn(oArgs.target));
});
The issue is, I have an initial column selected programmatically. I can highlight the other column, but it doesn't remove the selection from the initially-selected column.
You are correct - there is no quick clean solution.
YUI DataTable currently (as of 2.8) lacks an unselectAllColmns method to match unselectAllRows (which is called by onEventSelectRow).
It is also worth noting that onEventSelectColumn selects the column header, so unselectAllCells will not work.
You could implement your own unselectAllColumns() function like this:
function unselectAllColumns (dataTable) {
var i, oColumn, oColumnSet = dataTable.getColumnSet();
for (i=0; i<oColumnSet.keys.length; i++) {
oColumn = oColumnSet.keys[i];
if (oColumn.selected) {
dataTable.unselectColumn(oColumn);
}
}
}
This will be marginally more efficient than using getSelectedColumns() because you will not need to build an intermediate array of only selected columns (looking at the source getSelectedColumns calls getColumnSet and walks the array just as above).
I guess I can do this, but its not elegant. There has to be a better way.
myEndColDataTable.subscribe("cellClickEvent", function (oArgs) {
var colUnSelect = myEndColDataTable.getSelectedColumns();
myEndColDataTable.unselectColumn(colUnSelect[0]);
myEndColDataTable.selectColumn(myEndColDataTable.getColumn(oArgs.target));
});

Resources