Favorite Pages for Members
Heads Up!
This article is several years old now, and much has happened since then, so please keep that in mind while reading it.
There was a recent Umbraco blog post about doing something similar with Umbraco relations - check it out here - which involves using the API and some .Net coding.
Wouldn't it be even more fun if you did not have to launch Visual Studio to make this all work?
Below is a brief description of how I achieved just that with the help of some great packages and little bit of razor script and jquery.
The tools I used...
- uComponents Multi-Node Tree Picker
- Macro Service
If you are not familiar with Macro Service, you should check it out!
Setting up the member...
In my membership configuration, I created a dataType for myFavorites of type Multi-Node Tree Picker and added it to the memberType with an alias of myFavs.
The razor macros... Get to it already!
addFavorite.cshtml
@using umbraco.cms.businesslogic.member;
@using umbraco.NodeFactory;
@{
var member = Member.GetCurrentMember();
String myValue = @Model.Id.ToString();
List<string> ListPages = null;
if (member != null)
{
if (member.getProperty("myFavs")!= null && member.getProperty("myFavs").Value != null)
{
string value = member.getProperty("myFavs").Value.ToString();
if(String.IsNullOrEmpty(value)){
member.getProperty("myFavs").Value = myValue;
} else {
ListPages = value.Split(',').ToList();
if (!ListPages.Contains(myValue))
{
ListPages.Add(myValue);
member.getProperty("myFavs").Value = String.Join(",", ListPages.ToArray());
}
}
member.Save();
value = member.getProperty("myFavs").Value.ToString();
ListPages = value.Split(',').ToList();
}
}
}
<ul class="unstyled">
@foreach (var id in ListPages) {
var name = umbraco.library.GetItem(Int32.Parse(id),"nodeName");
<li><a href="#" rel="@id" class="btn btn-mini btn-danger delete">×</a> <a href="@umbraco.library.NiceUrl(Int32.Parse(id))">@name</a></li>
}
</ul>
removeFavorite.cshtml
@using umbraco.cms.businesslogic.member;
@{
var member = Member.GetCurrentMember();
String myValue = @Model.Id.ToString();
List<string> ListPages = null;
if (member != null)
{
if (member.getProperty("myFavs")!= null && member.getProperty("myFavs").Value != null)
{
string value = member.getProperty("myFavs").Value.ToString();
ListPages = value.Split(',').ToList();
if (ListPages.Contains(myValue))
{
ListPages.Remove(myValue);
member.getProperty("myFavs").Value = String.Join(",", ListPages.ToArray());
member.Save();
}
}
}
}
<ul class="unstyled">
@foreach (var id in ListPages) {
var name = umbraco.library.GetItem(Int32.Parse(id),"nodeName");
<li><a href="#" rel="@id" class="btn btn-mini btn-danger delete">×</a> <a href="@umbraco.library.NiceUrl(Int32.Parse(id))">@name</a></li>
}
</ul>
Setting up macro service...
So, now that you have the razor macros created, you need to set up the macro service(s). When you install the Macro Service package, it adds a tab to your macros. Simply select the macro you want to turn into a service and set up as you see below. For more info about macro service, please consult the package page on our.umbraco.org.
and...
Add the button to the page...
We use the rel attribute on the link to tell our macro what page to add to the member's favorites.
<a class="btn btn-small btn-success" href="#" id="addFav" rel="<umbraco:Item field="pageID" runat="server" />" ><i class="icon-thumbs-up"></i> Add To Favorites</a>
Some jQuery to tie it all together...
Use this jQuery snippet to add pages to the favorites box -
$('a#addFav').live("click", function(){
var theNode = $(this).attr('rel');
$('#favList').load('/feeds/addFav?nodeId='+ theNode);
})
and remove a favorite with this little bit -
$('a.delete').live("click", function(){
var theNode = $(this).attr('rel');
$('#favList').load('/feeds/RemoveFav?nodeId='+ theNode);
})
Oh, and I guess we need a little macro to list the favs too... well, for this, I decided to go back to my old school XSLT roots ;)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp " ">
<!ENTITY times "×">
]>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" xmlns:ucomponents.cms="urn:ucomponents.cms" xmlns:ucomponents.dates="urn:ucomponents.dates" xmlns:ucomponents.email="urn:ucomponents.email" xmlns:ucomponents.io="urn:ucomponents.io" xmlns:ucomponents.media="urn:ucomponents.media" xmlns:ucomponents.members="urn:ucomponents.members" xmlns:ucomponents.nodes="urn:ucomponents.nodes" xmlns:ucomponents.random="urn:ucomponents.random" xmlns:ucomponents.request="urn:ucomponents.request" xmlns:ucomponents.search="urn:ucomponents.search" xmlns:ucomponents.strings="urn:ucomponents.strings" xmlns:ucomponents.urls="urn:ucomponents.urls" xmlns:ucomponents.xml="urn:ucomponents.xml"
exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ucomponents.cms ucomponents.dates ucomponents.email ucomponents.io ucomponents.media ucomponents.members ucomponents.nodes ucomponents.random ucomponents.request ucomponents.search ucomponents.strings ucomponents.urls ucomponents.xml ">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:param name="currentPage"/>
<xsl:template match="/">
<xsl:variable name="theMember" select="umbraco.library:GetCurrentMember()" />
<xsl:if test="$theMember">
<div class="well well-small">
<h4>My Favorites</h4>
<div id="favList">
<xsl:if test="$theMember/myFavs != ''">
<ul class="unstyled">
<xsl:for-each select="umbraco.library:Split($theMember/myFavs, ',')/value">
<xsl:if test=". != ''">
<xsl:variable name="link" select="umbraco.library:NiceUrl(.)" />
<li>
<a href="#" rel="{.}" class="btn btn-mini btn-danger delete">×</a>
<a href="{$link}"><xsl:value-of select="umbraco.library:GetXmlNodeById(.)/@nodeName" /></a>
</li>
</xsl:if>
</xsl:for-each>
</ul>
</xsl:if>
</div>
</div>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
With that we are just about done! There are many modifications and enhancements that I know all of you can make to this, so have fun and enjoy your holiday season!
Bob Baty-Barr
Bob is on Twitter as @bootnumlock