Pagination in ListViewByQuery web part - sharepoint

I have written a web part that use ListViewByQuery to display the items based on query provided. Everything work perfect except pagination.
When I specify rowLimit it is displaying me only first set of record and pagination control is not visible so I could not able to move to next set of records.

The problem is that when you click on the paged button 1-2 it will postback adding some values in query string.
I accidentally remove the view=. query string from the URL and hit enter to get the results.
So what I did is as follows
if (!string.IsNullOrEmpty(Request.QueryString["View"]))
{
string queryString = string.Empty;
foreach (string key in Request.QueryString.Keys)
{
if (key.ToLower() != "view")
queryString += key + "=" + Request.QueryString[key] + "&";
}
SPUtility.Redirect(Request.Url.GetLeftPart(UriPartial.Path), SPRedirectFlags.Default, HttpContext.Current,queryString);
return;
}

Great answer Muhammad - after removing the view key and value, the link works fine.
However the line SPUtility.Redirect(.. didn't work for me.
Instead, as I put your code inside CreateChildControls() I used:
this.Context.Response.Redirect(this.Context.Request.Url.GetLeftPart(UriPartial.Path) + "?" + queryString);

Related

Hyperlink to page with smart search filter prepopulated

I have a smart search page that shows all the products on the page with some smart search filters that narrows down the products on some criterias (Let's say for example Filter1 has Option1, Option2 and Option3).
What I am trying to accomplish is to have a link on a seperate page that links to the product page, but when the user clicks on that link some of the search filters gets set (For example Filter1 would have Option2 selected).
I'm not sure if that is possible with out of the box solution, but with simple tweaks inside SearchFilter.ascx.cs, you can make a workaround. File is placed under CMSWebParts/SmartSearch/SearchFilter.ascx.cs. You should change method 'GetSelectedItems' to take a look into query string for filter value (see snippet bellow):
/// <summary>
/// Gets selected items.
/// </summary>
/// <param name="control">Control</param>
/// <param name="ids">Id's of selected values separated by semicolon</param>
private string GetSelectedItems(ListControl control, out string ids)
{
ids = "";
string selected = "";
//CUSTOM: retrive value for query string
var customFilter = QueryHelper.GetString("customFilter", "");
// loop through all items
for (int i = 0; i != control.Items.Count; i++)
{
//CUSTOM: ----START-----
if (!RequestHelper.IsPostBack())
{
if (!string.IsNullOrEmpty(customFilter))
{
if (control.Items[i].Text.Equals(customFilter, StringComparison.InvariantCultureIgnoreCase))
{
control.Items[i].Selected = true;
}
}
}
//CUSTOM: ----END-----
if (control.Items[i].Selected)
{
selected = SearchSyntaxHelper.AddSearchCondition(selected, control.Items[i].Value);
ids += ValidationHelper.GetString(i, "") + ";";
}
}
if (String.IsNullOrEmpty(selected) && (control.SelectedItem != null))
{
selected = control.SelectedItem.Value;
ids = control.SelectedIndex.ToString();
}
return selected;
}
And your hyperlink will look like this: /Search-result?searchtext=test&searchmode=anyword&customfilter=coffee
With this modifications, you can send only one value in filter, but if you need more then one value, you can send them and customize it however suits you best. Also, you can send filter name (in case that you have multiple filters) and then add check in method above.
I will recommend you not to modify kentico files. Instead of that, clone default filter web part and make modifications there, because withing next upgrade of project, you will lose your changes. I checked this in Kentico 11.
For Smart Search Filters:
if turn off auto-post back option -then web part control ID should become a query string parameter that you can use.
This above will form something like:
/Smart-search-filter.aspx?searchtext=abc&searchmode=anyword&wf=2;&ws=0;&wa=0
P.S. I suggest you to take a look at the corporate site example: look the smart search filter web part: /Examples/Web-parts/Full-text-search/Smart-search/Smart-search-filter. It is working example you can use it as starting point.

how do we add url parameters? (EJS + Node + Express)

I understood how we parse the url parameters in express routes, as in the example
How to get GET (query string) variables in Express.js on Node.js?
But where do the url parameters come from in the first place?
EDIT:
Apparently, I can build such a query with jquery (i.e $.get). I can append params to this query object. It s cool, but still i m trying to understand how we achieve this in the query that renders the page as a whole.
An example : when i choose the oldest tab below, how does SO add ?answertab=oldest to the url so it becomes :
https://stackoverflow.com/questions/30516497/how-do-we-add-url-parameters-ejs-node-express?answertab=oldest#tab-top
The string you're looking at is a serialization of the values of a form, or some other such method of inputing data. To get a sense of this, have a look at jQuery's built in .serialize() method.
You can construct that string manually as well, and that's pretty straight forward as well. The format is just ?var1=data1&var2=data2 etc. If you have a JSON object {"name": "Tim", "age": 22} then you could write a very simple function to serialize this object:
function serializeObject(obj) {
var str = "?";
for(var i = 0; i < Object.keys(obj).length; i++) {
key = Object.keys(obj)[i];
if (i === Object.keys(obj).length - 1)
str += encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]);
else
str += encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]) + "&";
}
return str;
}
Running seralizeObject({"name": "Tim", "age": 22}) will output '?name=Tim&age=22'. This could be used to generate a link or whatnot.
The page author writes them so. This is how they "come in the first place". The authors of an HTML page decide (or are told by website designers) where to take the user when he clicks on a particular anchor element on it. If they want users to GET a page with some query parameters (which their server handles), they simply add query string of their choice to the link's href attribute.
Take a look at the href attribute of the oldest tab you clicked:
<a
class="youarehere"
href="/questions/30516497/how-do-we-add-url-parameters-ejs-node-express?answertab=oldest#tab-top"
title="Answers in the order they were provided"
>
oldest
</a>
When you clicked it, the browser simply took you to path indicated in href attribute /questions/30516497/how-do-we-add-url-parameters-ejs-node-express?answertab=oldest#tab-top relative to the base URL http://stackoverflow.com. So the address bar changed.
stackoverflow.com may have its own system of generating dynamic HTML pages. Their administrators and page authors have configured their server to handle particular query parameters and have put in place their own methods to make sure that links on their pages point to the URL(including query string) they wish.
You need to provide URIs with query strings of your choice (you can build them using url.format and querystring.stringify) to your template system to render. Then make your express routes process them and generate pages depending on their value.

getting a list of forms that contain a specified field, is there a better method

The following code is a script object on an XPage in it I loop through an array of all the forms in a database, looking for all the forms that contain the field "ACIncludeForm". My method works but it takes 2 - 3 seconds to compute which really slows the load of the XPage. My question is - is there a better method to accomplish this. I added code to check to see if the sessionScope variable is null and only execute if needed and the second time the page loads it does so in under a second. So my method really consumes a lot of processor time.
var forms:Array = database.getForms();
var rtn = new Array;
for (i=0 ; i<forms.length; ++i){
var thisForm:NotesForm = forms[i];
var a = thisForm.getFields().indexOf("ACIncludeForm");
if (a >= 0){
if (!thisForm.isSubForm()) {
if (thisForm.getAliases()[0] == ""){
rtn.push(thisForm.getName() + "|" + thisForm.getName() );
}else{
rtn.push(thisForm.getName() + "|" + thisForm.getAliases()[0] );
}
}
}
thisForm.recycle()
}
sessionScope.put("ssAllFormNames",rtn)
One approach would be to build an index of forms by yourself. For example, create an agent (LotusScript or Java) that gets all forms and for each form, create a document with for example a field "form" containing the form name and and a field "fields" containing all field names (beware of 32K limit).
Then create a view that displays all these documents and contains the value of the "fields" field in the first column so that each value of this field creates one line in this view.
Having such a view, you can simply make a #DbLookup from your XPage.
If your forms are changed, you only need to re-run the agent to re-build your index. The #DbLookup should be pretty fast.
Place the form list in a static field of a Java class. It will stay there for a long time (maybe until http boot). In my experience applicationScope values dissappear in 15 minutes.

Lucene Search for SiteCore get Field content from result

Hy. I have run into a small problem. I am using Lucene Search and I am trying to get the content from a field in the returned result. I have got so far until the ID's of the field. Right now i get the field's ID' like that.
foreach (var i in hit.Template.InnerItem.InnerData.Fields)
{
hitParagraph = hitParagraph + i.ToString();
}
This gives me the ID's of the field inside that template like this
[{25BED78C-4957-4165-998A-CA1B52F67497}, 20130307T051813][{5DD74568-4D4B-44C1-B513-0AF5F4CDA34F}, vh\branea1][{8CDC337E-A112-42FB-BBB4-4143751E123F}, 51885b42-bf8b-4f26-8259-125d352457f3][{D9CF14B1-FA16-4BA6-9288-E8A174D4D522}, .....
Please some help.
Thank You
I'm not entirely sure what you're after. If it's the content of a specific field, you could just use hit["fieldname"] (assuming hit is a Sitecore item). Or hit.Template.InnerItem["fieldname"] would work, I think.
I think you don't need the InnerData bit - if you want a foreach loop I think you could do it like so:
foreach (Field i in hit.Template.InnerItem.Fields)
{
hitParagraph += i.Value.ToString();
}
From what I understand from your code, the hit is a Sitecore Item class instance. To get all the fields from it, use:
hit.Fields.ReadAll();
foreach (Field field in hit.Fields)
{
hitParagraph = hitParagraph + field.Key + ": " + item[field.Key] + "\n";
}

SharePoint : Guessing the attachment path before updating a list item

I have some code that inserts a list item into a list...
I then have this code
SPFolder folder = web.Folders["Lists"].SubFolders[list.RootFolder.Name].SubFolders["Attachments"].SubFolders[item.ID.ToString()];
foreach (SPFile file in folder.Files)
{
string attachmentName = this.downloadedMessageID + ".xml";
if (file.Name == attachmentName)
{
SPFieldUrlValue value = new SPFieldUrlValue();
value.Description = this.downloadedMessageID + ".xml";
value.Url = this.SiteAddress + file.Url;
item["ZFO"] = value;
}
}
this is fine except for one problem... before this code actually works... I need to call the item.update() method to save the item to SharePoint...
But as you can see there is more work to do ... after item.update is called...
So this means... I have
work
item.update();
more work
item.update();
The problem I am having is I really want just
work
item.update();
So that in any event of failure the whole thing will fail at once or pass at once.... (almost like a SQL transaction).
So whats preventing me from doing this is - I need to set a hyperlink to one of the fields in the list item, this will be to an attachment in the list attachments collection.
Is there any way I can predict this address without having saved the list item to MOSS?
An attachment path depends on the item ID, and I don't believe your item will have an ID until you save it. Have you considered storing the attachments in a document library instead, linked by the field you're trying to set?
Transactional operation isn't exactly SharePoint's strong suit.

Resources