Hi, I have an umbraco V4 website that has the following structure:
Jobs -Categories -Cat 1 -Job 1 -Job 2 -Job 3 -Cat 2 -Job 4 -Job 5 Locations - London - South East - North
I have created an ultimate picker dropdown list that is populated by the locations node and this is a property of the Job document type, therefore Job 1 is in Category 1 and may have London selected as the location.
I want to be able to do a search using two drop down lists based on the category and the location. I have so far created the XSLT below which creates the two drop down lists but I am unsure as to where I go from here and whether what I am trying to achieve is going to be possible using XSLT. Can anyone give me a nudge in the right direction? I want there to be a Search button that the using clicks to search after selecting the options in the two drop downs and I want the results to be displayed on a different page. Many thanks. This is the XSLT I have so far, as you can see it is not much!
+1 on the totally doable in xslt (with some wrestling) - we did http://www.haddenrankin.com/sell-with-us.aspx for searching properties - the properties come in via an xml file and we search using only xslt.
Basically all you're doing is creating a form which sends to a new page, then using umbraco.library:Request to grab the querystring values and use them as filters in the xslt, much as you do for e.g. "umbracoNaviHide = '1'" etc.
Thanks for the replies, that's good news to hear that it can be done, the bad news is that I'm stuck as to how I do it, I have never used umbraco.library:request before and do not have a lot of experience with forms either :-(
Where the action is pointing to your results page. Now on the template of your results page you'll need some xslt that requests the querystring and applies filters based on it.
Such as on my property search example, I was wanting to check for "minimum rooms". I set up an xslt variable then request the value from the querystring, supplying a fallback in case of errrors.
Just like a normal umbraco loop (except above the "Bedrooms" label is a node, not an attribute as in umbraco. The above is a simple example - the full for-each looked more like
<xsl:for-each select="$feed/RegistrationExtraction/RegistrationList/Registration [contains(Exslt.ExsltStrings:lowercase(./Area), Exslt.ExsltStrings:lowercase($area)) and (./RegistrationType = 'Sale') and (./AskingPrice < $maxprice) and (./Bedrooms >= $minrooms)]"/>
You can see how it builds in size over time, but essentially theres a lot of repeating fundamental concepts that you'll already be used to from working with umbraco for a little while.
Also, if you're having trouble with the form you can test your results by just modifying the querystring manually in the browser.
Dan
p.s. another thing I find useful is to enable a "debug" option in the xslt, just create a variable and switch it from 1 to 0 or whatever, then you could have something like below - just printing out the values of all your variables to make sure everything is working as needed.
Many thanks, that has got me started but already I am a little stuck. I have left the form for now and will deal with that later but I have got the following XSLT for my results page but I am not sure as to how I modify my for-each to check for the category and location. The nodes I am looking for are child nodes of Categorie folders so my first bit works fine, if the query string category equals the node ID of a category then all the child nodes are listed, I now want it to be able to find the child nodes if they have a property type that is equal to the location query string (the location property type is an ultimate picker so it should be node ID I believe). I'm assuming I need some sort of "and" command but my XSLT knowledge is letting me down!! This is what I have so far:
Excellent, thanks once again Dan, that has been so much help. Think I have now got it cracked, just need to get my form XSLT setup to pass the query strings and sort out my styling. Just for anyone that is interested this is my XSLT for the search results page. Please let me know if you have any questions or if there is anything in there you think I could be doing a better way. This is the most complex XSLT I have written so far therefore I'm sure there will be errors or bad practices.
<!-- GET CATEGORY QUERY STRING --> <xsl:variable name="category"> <xsl:choose> <xsl:when test="umbraco.library:Request('category') <= 0 or string(umbraco.library:Request('category')) = '' or string(umbraco.library:Request('category')) = 'NaN'">0</xsl:when> <xsl:otherwise> <xsl:value-of select="umbraco.library:Request('category')"/> </xsl:otherwise> </xsl:choose> </xsl:variable>
<!-- GET LOCATION QUERY STRING --> <xsl:variable name="location"> <xsl:choose> <xsl:when test="umbraco.library:Request('location') <= 0 or string(umbraco.library:Request('location')) = '' or string(umbraco.library:Request('location')) = 'NaN'">0</xsl:when> <xsl:otherwise> <xsl:value-of select="umbraco.library:Request('location')"/> </xsl:otherwise> </xsl:choose> </xsl:variable>
<xsl:choose> <!-- RESULTS WHEN CATEGORY IS ANY AND LOCATION IS SELECTED --> <xsl:when test="$category = 'any' and $location != 'any'"> <xsl:for-each select="umbraco.library:GetXmlNodeById(1148)//node[@nodeTypeAlias='Job' and string(data [@alias='umbracoNaviHide']) != '1' and string(data [@alias='location']) = $location]">
<!-- RESULTS WHEN LOCATION IS ANY AND CATEGORY IS SELECTED --> <xsl:when test="$location = 'any' and $category != 'any'"> <xsl:for-each select="umbraco.library:GetXmlNodeById($category)/node [string(data [@alias='umbracoNaviHide']) != '1']">
<!-- RESULTS WHEN CATEGORY AND LOCATION ARE BOTH ANY --> <xsl:when test="$category = 'any' and $location = 'any'"> <xsl:for-each select="umbraco.library:GetXmlNodeById(1148)//node[@nodeTypeAlias='Job']"> <a href="{umbraco.library:NiceUrl(@id)}"> <xsl:value-of select="@nodeName"/> </a> </xsl:for-each> </xsl:when>
<!-- RESULTS WHEN CATEGORY AND LOCATION ARE BOTH SELECTED --> <xsl:otherwise> <xsl:for-each select="umbraco.library:GetXmlNodeById($category)/node [string(data [@alias='umbracoNaviHide']) != '1' and string(data [@alias='location']) = $location]">
Sorry, one more question. I have created my form but the problem is because it is within another form (the top level masterpage has a form that covers the whole page) it does not work. How can I get around this issue?
My firstport of call would be to determine if the runat=server form around your whole page is necessary. I usually only use these directly around areas that need them, e.g. if doc2form is to be insterted in an editor field I'll wrap that in a form runat=server. I think "canvas editing" requires a form, but I don't really use this much anyway.
If the main form really is necessary, you'll need to use some javascript to submit the form.
I don't think it is, I was under the impression that all asp.net pages should be wrapped in a form that is why I always put a form directly after my body tag on the top level master. Is this not the case?
It's not strictly necessary unless you're using particular controls inside the page. It's basically there as a asp.net bastardisation of html, injecting "statefulness" into a medium never designed for it.
I'd remove it and only re-add in circumstances where it is needed (doc2form, contour etc),
Ok thanks, that is excellent. I have now got it working as I want. I have even created another template in the XSLT that shows the results as I want them and have set each "when" command to call that template rather than having to repeat all the CSS etc everytime. Once again thanks for all your help.
Then this is the XSLT for my search results page that grabs the querystrings created using the above and then displays the nodes accordingly:
<xsl:template match="/">
<!-- GET CATEGORY QUERY STRING --> <xsl:variable name="categoryquery"> <xsl:choose> <xsl:when test="umbraco.library:Request('category') <= 0 or string(umbraco.library:Request('category')) = '' or string(umbraco.library:Request('category')) = 'NaN'">0</xsl:when> <xsl:otherwise> <xsl:value-of select="umbraco.library:Request('category')"/> </xsl:otherwise> </xsl:choose> </xsl:variable>
<!-- GET LOCATION QUERY STRING --> <xsl:variable name="locationquery"> <xsl:choose> <xsl:when test="umbraco.library:Request('location') <= 0 or string(umbraco.library:Request('location')) = '' or string(umbraco.library:Request('location')) = 'NaN'">0</xsl:when> <xsl:otherwise> <xsl:value-of select="umbraco.library:Request('location')"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:choose>
<!-- RESULTS WHEN CATEGORY IS ANY AND LOCATION IS SELECTED --> <xsl:when test="$categoryquery = 'any' and $locationquery != 'any'"> <xsl:for-each select="umbraco.library:GetXmlNodeById(1148)//node[@nodeTypeAlias='Job' and string(data [@alias='umbracoNaviHide']) != '1' and string(data [@alias='location']) = $locationquery]"> <xsl:call-template name="displayResults"> </xsl:call-template>
</xsl:for-each> <xsl:if test="count(umbraco.library:GetXmlNodeById(1148)//node [@nodeTypeAlias='Job' and string(data [@alias='umbracoNaviHide']) != '1' and string(data [@alias='location']) = $locationquery]) = 0"> <p>Your search returned no results</p> <br /> <a href="/browse-all-jobs.aspx">Click here to browse all jobs</a> </xsl:if> </xsl:when>
<!-- RESULTS WHEN LOCATION IS ANY AND CATEGORY IS SELECTED --> <xsl:when test="$locationquery = 'any' and $categoryquery != 'any'"> <xsl:for-each select="umbraco.library:GetXmlNodeById($categoryquery)/node [string(data [@alias='umbracoNaviHide']) != '1']">
</xsl:for-each> <xsl:if test="count(umbraco.library:GetXmlNodeById($categoryquery)/node [string(data [@alias='umbracoNaviHide']) != '1' ]) = 0"> <p>Your search returned no results</p> <br /> <a href="/browse-all-jobs.aspx">Click here to browse all jobs</a> </xsl:if> </xsl:when>
<!-- RESULTS WHEN CATEGORY AND LOCATION ARE BOTH ANY --> <xsl:when test="$categoryquery = 'any' and $locationquery = 'any'"> <xsl:for-each select="umbraco.library:GetXmlNodeById(1148)//node[@nodeTypeAlias='Job']"> <xsl:call-template name="displayResults"> </xsl:call-template>
</xsl:for-each>
</xsl:when>
<!-- RESULTS WHEN CATEGORY AND LOCATION ARE BOTH SELECTED --> <xsl:otherwise> <xsl:for-each select="umbraco.library:GetXmlNodeById($categoryquery)/node [string(data [@alias='umbracoNaviHide']) != '1' and string(data [@alias='location']) = $locationquery]">
Search based on dropdowns using XSLT
Hi, I have an umbraco V4 website that has the following structure:
Jobs
-Categories
-Cat 1
-Job 1
-Job 2
-Job 3
-Cat 2
-Job 4
-Job 5
Locations
- London
- South East
- North
I have created an ultimate picker dropdown list that is populated by the locations node and this is a property of the Job document type, therefore Job 1 is in Category 1 and may have London selected as the location.
I want to be able to do a search using two drop down lists based on the category and the location. I have so far created the XSLT below which creates the two drop down lists but I am unsure as to where I go from here and whether what I am trying to achieve is going to be possible using XSLT. Can anyone give me a nudge in the right direction? I want there to be a Search button that the using clicks to search after selecting the options in the two drop downs and I want the results to be displayed on a different page. Many thanks. This is the XSLT I have so far, as you can see it is not much!
Hi,
It's absolutely doable. I created something like that. A year a go I implemented this:
I think I used xsltsearch as a starter but I could be wrong there. But it's xslt all the way.
I'll check if I have the source if you're interested?
/Jesper Ordrup
+1 on the totally doable in xslt (with some wrestling) - we did http://www.haddenrankin.com/sell-with-us.aspx for searching properties - the properties come in via an xml file and we search using only xslt.
Basically all you're doing is creating a form which sends to a new page, then using umbraco.library:Request to grab the querystring values and use them as filters in the xslt, much as you do for e.g. "umbracoNaviHide = '1'" etc.
Thanks for the replies, that's good news to hear that it can be done, the bad news is that I'm stuck as to how I do it, I have never used umbraco.library:request before and do not have a lot of experience with forms either :-(
OK here's a very quick rundown - any more would probably require a blog post over on geckonewmedia.com
So, you have a dropdown with your categories and with your locations. This is a good start. Now, just wrap these in a form like
Where the action is pointing to your results page. Now on the template of your results page you'll need some xslt that requests the querystring and applies filters based on it.
Such as on my property search example, I was wanting to check for "minimum rooms". I set up an xslt variable then request the value from the querystring, supplying a fallback in case of errrors.
This just looks for a querystring value of the format
and applies it to an xslt variable. Now we have the variable we can apply a filter to our for-each
Just like a normal umbraco loop (except above the "Bedrooms" label is a node, not an attribute as in umbraco. The above is a simple example - the full for-each looked more like
You can see how it builds in size over time, but essentially theres a lot of repeating fundamental concepts that you'll already be used to from working with umbraco for a little while.
Also, if you're having trouble with the form you can test your results by just modifying the querystring manually in the browser.
Dan
p.s. another thing I find useful is to enable a "debug" option in the xslt, just create a variable and switch it from 1 to 0 or whatever, then you could have something like below - just printing out the values of all your variables to make sure everything is working as needed.
Hope this starts you on the right direction!
Dan
Hi Dan,
Many thanks, that has got me started but already I am a little stuck. I have left the form for now and will deal with that later but I have got the following XSLT for my results page but I am not sure as to how I modify my for-each to check for the category and location. The nodes I am looking for are child nodes of Categorie folders so my first bit works fine, if the query string category equals the node ID of a category then all the child nodes are listed, I now want it to be able to find the child nodes if they have a property type that is equal to the location query string (the location property type is an ultimate picker so it should be node ID I believe). I'm assuming I need some sort of "and" command but my XSLT knowledge is letting me down!! This is what I have so far:
What about this?
Also might be worth sticking in something like
Dan
Excellent, thanks once again Dan, that has been so much help. Think I have now got it cracked, just need to get my form XSLT setup to pass the query strings and sort out my styling. Just for anyone that is interested this is my XSLT for the search results page. Please let me know if you have any questions or if there is anything in there you think I could be doing a better way. This is the most complex XSLT I have written so far therefore I'm sure there will be errors or bad practices.
Sorry, one more question. I have created my form but the problem is because it is within another form (the top level masterpage has a form that covers the whole page) it does not work. How can I get around this issue?
My firstport of call would be to determine if the runat=server form around your whole page is necessary. I usually only use these directly around areas that need them, e.g. if doc2form is to be insterted in an editor field I'll wrap that in a form runat=server. I think "canvas editing" requires a form, but I don't really use this much anyway.
If the main form really is necessary, you'll need to use some javascript to submit the form.
I don't think it is, I was under the impression that all asp.net pages should be wrapped in a form that is why I always put a form directly after my body tag on the top level master. Is this not the case?
It's not strictly necessary unless you're using particular controls inside the page. It's basically there as a asp.net bastardisation of html, injecting "statefulness" into a medium never designed for it.
I'd remove it and only re-add in circumstances where it is needed (doc2form, contour etc),
Dan
Ok thanks, that is excellent. I have now got it working as I want. I have even created another template in the XSLT that shows the results as I want them and have set each "when" command to call that template rather than having to repeat all the CSS etc everytime. Once again thanks for all your help.
No problem at all, glad you got it sorted. I'm still surprised by how much is possible in xslt!
Hi, did you get this all working ok? I am trying to do the same as we speak!
Yeah, what do you need to know?
I started trying to do this with xslt seach and got so far and got stuck. This looks like a more direct root and I wanted to see how you did it.
This is the XSLT for the dropdowns that I had on my homepage:
Then this is the XSLT for my search results page that grabs the querystrings created using the above and then displays the nodes accordingly:
Let me know if there are any bits that you do not understand or you want me to explain more.
Thanks for this, I am going to work through it this weekend
is working on a reply...