Displaying DocumentsAndFiles in Product Detail Widget Template
Hello,
I have a series of products that can be purchased as printed and shipped brochures. But, each of these brochures is also available as a free PDF download. I have added the PDF to the products as a "Documents and Other Files", but the widget template doesn't display the file at all.
When I go into Design > Widget Templates, and I click to edit the template for "Product Details". In the "Insert..." bar on the right, under "Other Data" there are two possible fields:
When I click to add "DocumentsAndFiles" it puts in this code:
<
sitefinity:TextField
runat
=
"server"
DisplayMode
=
"Read"
Value='<%# Eval("DocumentsAndFiles")%>' />
Which obviously doesn't help as it just does a .toString() apparently, and the page prints out:
System.Collections.Generic.List`1[Telerik.Sitefinity.Ecommerce.Catalog.Model.ProductFile]
How can I at least grab the first list item and snag it's content URL, so that I can fill in something like this for the template:
<
a
href='<%# (System.Collections.Generic.List)Eval("DocumentsAndFiles")[0].DocumentUrl %>'>FREE PDF - Download Now</
a
>
Thanks,
Brandon
OK, so I have more info on this topic, but may need a fresh set of eyes to help really identify it...
The required tag for adding the files to the page (I got from the default template for Product Details):
1.
<
div
class
=
"sfProductDocumentsAndFiles"
>
2.
<
sf:ProductDocumentsAndFilesControl
id
=
"productDocumentsAndFilesControl"
ProductItem='<%# Page.GetDataItem() %>' runat="server" />
3.
</
div
>
So I added the above code to my template, and it puts on the rendered container DIV for the DocumentsAndFiles, but it is empty, like this:
1.
<
div
class
=
"sfProductDocumentsAndFiles"
>
2.
<
div
id
=
"ctl00_BodyContent_C004_productsFrontendDetail_ctl00_ctl00_SingleItemContainer_ctrl0_productDocumentsAndFilesControl"
></
div
>
3.
</
div
>
I then compared my template file to the default one, making sure all the control directives at the top matched. They do. I noticed that my "sfProductDocumentsAndFiles" DIV though was not under the same parent DIV as the default, so I moved it to be inside the "sfproductInfoWrp" DIV just like the default template does. ...strangely, at this point, I saw the download link (with PDF icon) and it worked...the first time I viewed the page...after that coming back to the page, it hasn't shown up again...
Here's the code I'm using in the template that I *want* to use:
001.
<%@ Control Language="C#" %>
002.
<%@ Import Namespace="System.ComponentModel" %>
003.
<%@ Import Namespace="Telerik.Sitefinity.Ecommerce.Catalog.Model" %>
004.
<%@ Register Assembly="Telerik.Sitefinity.Ecommerce" Namespace="Telerik.Sitefinity.Modules.Ecommerce.Orders.Web.UI"
005.
TagPrefix="sfOrders" %>
006.
<%@ Register Assembly="Telerik.Sitefinity.Ecommerce" Namespace="Telerik.Sitefinity.Modules.Ecommerce.Catalog.Web.UI.Fields"
007.
TagPrefix="sfCatalog" %>
008.
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.ContentUI" Assembly="Telerik.Sitefinity" %>
009.
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI" Assembly="Telerik.Sitefinity" %>
010.
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.PublicControls.BrowseAndEdit"
011.
Assembly="Telerik.Sitefinity" %>
012.
<%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
013.
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Modules.Ecommerce.Catalog.Web.UI"
014.
Assembly="Telerik.Sitefinity.Ecommerce" %>
015.
<%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI.Fields"
016.
TagPrefix="sfFields" %>
017.
<%@ Register Assembly="InGen.Sitefinity.ProductReviews" Namespace="InGen.Sitefinity.ProductReviews" TagPrefix="ipr" %>
018.
<
sf:ResourceLinks
id
=
"resourcesLinks"
runat
=
"server"
>
019.
<
sf:ResourceFile
JavaScriptLibrary
=
"JQueryFancyBox"
/>
020.
</
sf:ResourceLinks
>
021.
<
sf:ResourceLinks
id
=
"resourcesLinks2"
runat
=
"server"
UseEmbeddedThemes
=
"true"
Theme
=
"Default"
>
022.
<
sf:ResourceFile
Name
=
"Telerik.Sitefinity.Resources.Themes.Basic.Styles.fancybox.css"
023.
Static
=
"true"
/>
024.
</
sf:ResourceLinks
>
025.
<
div
id
=
"widgetStatus"
runat
=
"server"
visible
=
"false"
class
=
"sfErrorSummary sfTopMsg"
>
026.
<
asp:Label
ID
=
"widgetStatusMessage"
runat
=
"server"
/>
027.
</
div
>
028.
<
div
class
=
"sfproductDetailsWrp"
>
029.
<
sf:ConditionalTemplateContainer
ID
=
"conditionalTemplate"
runat
=
"server"
>
030.
<
templates
>
031.
<
sf:ConditionalTemplate
Left
=
"IsActive"
Operator
=
"Equal"
Right
=
"false"
runat
=
"server"
>
032.
<
asp:Literal
ID
=
"Literal1"
runat
=
"server"
Text="<%$Resources:OrdersResources, ProductNotAvailable %>" />
033.
</
sf:ConditionalTemplate
>
034.
035.
<
sf:ConditionalTemplate
Left
=
"IsActive"
Operator
=
"Equal"
Right
=
"true"
runat
=
"server"
>
036.
<
telerik:RadListView
ID
=
"SingleItemContainer"
ItemPlaceholderID
=
"ItemContainer"
AllowPaging
=
"False"
runat
=
"server"
EnableEmbeddedSkins
=
"false"
EnableEmbeddedBaseStylesheet
=
"false"
>
037.
<
LayoutTemplate
>
038.
<
div
class
=
"sfproductDetails sfClearfix"
>
039.
<
asp:PlaceHolder
ID
=
"ItemContainer"
runat
=
"server"
/>
040.
</
div
>
041.
</
LayoutTemplate
>
042.
<
ItemTemplate
>
043.
<
div
class
=
"sfproductInfoWrp"
>
044.
045.
<
span
class
=
"promo-callout"
>
046.
<%# (Eval("SpecialPromoNew") == null || (bool)Eval("SpecialPromoNew") == false) ? "" : "<
span
class
=
'new'
>New</
span
>" %>
047.
<%# (Eval("SpecialPromoUpdated") == null || (bool)Eval("SpecialPromoUpdated") == false) ? "" : "<
span
class
=
'updated'
>Updated</
span
>" %>
048.
<%# (Eval("SpecialPromoReduced") == null || (bool)Eval("SpecialPromoReduced") == false) ? "" : "<
span
class
=
'reduced'
>Reduced Price</
span
>" %>
049.
<%# (Eval("SpecialPromoLimited") == null || (bool)Eval("SpecialPromoLimited") == false) ? "" : "<
span
class
=
'limited'
>Limited Quantity</
span
>" %>
050.
</
span
>
051.
052.
<
h1
class
=
"sfproductTitle"
>
053.
<%# Eval("Title") %>
054.
</
h1
>
055.
<
div
class
=
"product-modified-date"
>
056.
<
sitefinity:TextField
runat
=
"server"
DisplayMode
=
"Read"
Value='<%# Eval("LastModified")%>' />
057.
</
div
>
058.
<
div
class
=
"sfproductDescription"
>
059.
<%# Eval("Description") %>
060.
</
div
>
061.
<
div
class
=
"sfproductSpecs clearfix"
>
062.
<%# Eval("Specifications") == null ? "" : "<
br
/>" + Eval("Specifications") %>
063.
</
div
>
064.
<
div
class
=
"sfProductDocumentsAndFiles"
>
065.
<
a
href
=
'#'
>FREE PDF - Download Now</
a
>
066.
<
sf:ProductDocumentsAndFilesControl
id
=
"productDocumentsAndFilesControl"
ProductItem='<%# Page.GetDataItem() %>' runat="server" />
067.
</
div
>
068.
</
div
>
069.
<
div
class
=
"product-detail-left"
>
070.
071.
072.
073.
<
div
class
=
"rule"
> </
div
>
074.
075.
<
div
class
=
"sfproductOptions clearfix"
>
076.
<
sf:ProductOptionsControl
id
=
"productOptionsControl"
ProductItem='<%# Page.GetDataItem() %>' runat="server" />
077.
</
div
>
078.
079.
<
div
class
=
"sfproductPrice"
>
080.
<
sfCatalog:DisplayPriceField
runat
=
"server"
ObjectType
=
"Product"
ObjectId='<%# Eval("Id") %>' />
081.
</
div
>
082.
083.
084.
<
div
class='sfproductAddtoCart <%# (Eval("CalltoOrder") == null || (bool)Eval("CallToOrder") == false) ? "" : "hide" %>'>
085.
<
sfOrders:AddToCartWidget
ID
=
"addToCartWidget"
ProductId='<%# Eval("Id") %>' runat="server" />
086.
</
div
>
087.
088.
<
div
class='sfproductCallToOrder <%# (Eval("CalltoOrder") == null || (bool)Eval("CallToOrder") == false) ? "hide" : "" %>'>
089.
<
div
class
=
"prmCust hide"
>For Premium Customization:</
div
>
090.
Contact <
b
>Vince Stone</
b
> at <
b
>800-638-9797 Ext. 2610</
b
> <
br
/>
091.
or <
a
href
=
"mailto:vinston@atlasworldgroup.com"
>vinston@atlasworldgroup.com</
a
>
092.
</
div
>
093.
094.
<
div
class
=
"sfproductImgsWrp"
>
095.
<
div
class
=
"sfproductMainImgWrp"
>
096.
<%-- This is so that we can have the rel="fancybox" without resorting to an Attributes.Add() call --%>
097.
<%-- <
a
href='<%# HttpUtility.HtmlAttributeEncode(Eval("PrimaryImageUrl") as string) %>' rel="fancybox"> --%>
098.
<
img
src='<%# HttpUtility.HtmlAttributeEncode(Eval("PrimaryImageUrl") as string) %>' alt='<%# HttpUtility.HtmlAttributeEncode(Eval("ThumbnailAlternativeText") as string) %>' />
099.
<%-- </
a
> --%>
100.
</
div
>
101.
102.
103.
<
asp:PlaceHolder
ID
=
"socialContainer"
runat
=
"server"
></
asp:PlaceHolder
>
104.
</
div
>
105.
106.
107.
<
div
class
=
"sfProductTagsWrp"
>
108.
<
h3
>Tags</
h3
>
109.
<
sitefinity:FlatTaxonField
ID
=
"FlatFieldControl"
DisplayMode
=
"Read"
runat
=
"server"
WebServiceUrl
=
"~/Sitefinity/Services/Taxonomies/FlatTaxon.svc"
AllowMultipleSelection
=
"true"
TaxonomyId
=
"CB0F3A19-A211-48a7-88EC-77495C0F5374"
TaxonomyMetafieldName
=
"Tags"
Expanded
=
"false"
ExpandText
=
"ClickToAddTags"
BindOnServer
=
"true"
HideWhenNoTaxaFound
=
"true"
/>
110.
</
div
>
111.
112.
</
div
>
113.
<
div
class
=
"product-detail-right"
>
114.
<
div
class
=
"product-detail-favorites"
>
115.
116.
117.
<
fav:FavoriteButtonView
118.
ImageUrl
=
"~/resources/favorite.png"
119.
FavoritedImageUrl
=
"~/resources/delete.png"
120.
ID
=
"FavoriteButton1"
121.
ContentType
=
"Products"
122.
ItemId='<%# Eval("Id") %>'
123.
ShowFavoritesCount="true"
124.
LayoutTemplatePath="~/resources/Favorites/FavoriteButtonLayout.ascx"
125.
runat="server" />
126.
127.
128.
</
div
>
129.
<
div
class
=
"product-detail-reviews"
>
130.
<
ipr:ProductReviewList
ID
=
"ProdReviewList"
ProductId='<%# Eval("Id") %>' ReviewTextRows='5' ReviewTextCols='50' runat="server" />
131.
</
div
>
132.
</
div
>
133.
134.
</
ItemTemplate
>
135.
</
telerik:RadListView
>
136.
</
sf:ConditionalTemplate
>
137.
</
templates
>
138.
</
sf:ConditionalTemplateContainer
>
139.
</
div
>
For the record...Everything else on the page displays just fine. No errors, or anything like that.
And for reference, here is the code from the default Product Detail template:
01.
<%@ Control Language="C#" %>
02.
<%@ Import Namespace="System.ComponentModel" %>
03.
<%@ Import Namespace="Telerik.Sitefinity.Ecommerce.Catalog.Model" %>
04.
<%@ Register Assembly="Telerik.Sitefinity.Ecommerce" Namespace="Telerik.Sitefinity.Modules.Ecommerce.Orders.Web.UI"
05.
TagPrefix="sfOrders" %>
06.
<%@ Register Assembly="Telerik.Sitefinity.Ecommerce" Namespace="Telerik.Sitefinity.Modules.Ecommerce.Catalog.Web.UI.Fields"
07.
TagPrefix="sfCatalog" %>
08.
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.ContentUI" Assembly="Telerik.Sitefinity" %>
09.
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI" Assembly="Telerik.Sitefinity" %>
10.
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.PublicControls.BrowseAndEdit"
11.
Assembly="Telerik.Sitefinity" %>
12.
<%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
13.
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Modules.Ecommerce.Catalog.Web.UI"
14.
Assembly="Telerik.Sitefinity.Ecommerce" %>
15.
<%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI.Fields"
16.
TagPrefix="sfFields" %>
17.
<
sf:ResourceLinks
id
=
"resourcesLinks"
runat
=
"server"
>
18.
<
sf:ResourceFile
JavaScriptLibrary
=
"JQueryFancyBox"
/>
19.
</
sf:ResourceLinks
>
20.
<
sf:ResourceLinks
id
=
"resourcesLinks2"
runat
=
"server"
UseEmbeddedThemes
=
"true"
Theme
=
"Default"
>
21.
<
sf:ResourceFile
Name
=
"Telerik.Sitefinity.Resources.Themes.Basic.Styles.fancybox.css"
22.
Static
=
"true"
/>
23.
</
sf:ResourceLinks
>
24.
<
div
id
=
"widgetStatus"
runat
=
"server"
visible
=
"false"
class
=
"sfErrorSummary sfTopMsg"
>
25.
<
asp:Label
ID
=
"widgetStatusMessage"
runat
=
"server"
/>
26.
</
div
>
27.
<
div
class
=
"sfproductDetailsWrp"
>
28.
<
sf:ConditionalTemplateContainer
ID
=
"conditionalTemplate"
runat
=
"server"
>
29.
<
templates
>
30.
<
sf:ConditionalTemplate
Left
=
"IsActive"
Operator
=
"Equal"
Right
=
"false"
runat
=
"server"
>
31.
<
asp:Literal
ID
=
"Literal1"
runat
=
"server"
Text="<%$Resources:OrdersResources, ProductNotAvailable %>" />
32.
</
sf:ConditionalTemplate
>
33.
34.
<
sf:ConditionalTemplate
Left
=
"IsActive"
Operator
=
"Equal"
Right
=
"true"
runat
=
"server"
>
35.
<
telerik:RadListView
ID
=
"SingleItemContainer"
ItemPlaceholderID
=
"ItemContainer"
AllowPaging
=
"False"
runat
=
"server"
EnableEmbeddedSkins
=
"false"
EnableEmbeddedBaseStylesheet
=
"false"
>
36.
<
LayoutTemplate
>
37.
<
div
class
=
"sfproductDetails sfClearfix"
>
38.
<
asp:PlaceHolder
ID
=
"ItemContainer"
runat
=
"server"
/>
39.
</
div
>
40.
</
LayoutTemplate
>
41.
<
ItemTemplate
>
42.
<
div
class
=
"sfproductImgsWrp"
>
43.
<
div
class
=
"sfproductMainImgWrp"
>
44.
<%-- This is so that we can have the rel="fancybox" without resorting to an Attributes.Add() call --%>
45.
<
a
href='<%# HttpUtility.HtmlAttributeEncode(Eval("PrimaryImageUrl") as string) %>' rel="fancybox">
46.
<
img
src='<%# HttpUtility.HtmlAttributeEncode(Eval("Thumbnail.Url") as string) %>' alt='<%# HttpUtility.HtmlAttributeEncode(Eval("ThumbnailAlternativeText") as string) %>' />
47.
</
a
>
48.
</
div
>
49.
50.
<
div
class
=
"sfproductImgsListWrp"
>
51.
<
ul
class
=
"sfproductImgsList"
>
52.
<
asp:Repeater
ID
=
"Repeater1"
runat
=
"server"
DataSource='<%# new BindingList<ProductImage>(((IEnumerable<
ProductImage
>)Eval("Images")).Skip(1).ToList()) %>'>
53.
<
ItemTemplate
>
54.
<
li
class
=
"sfproductImgWrp"
>
55.
<
a
href='<%# DataBinder.Eval(Container.DataItem, "Url") %>' rel="fancybox" class="sfproductImgLnk">
56.
<
asp:Image
ID
=
"Image1"
CssClass
=
"sfproductImg"
runat
=
"server"
ImageUrl='<%# DataBinder.Eval(Container.DataItem, "ThumbnailUrl") %>' Width='<%# (int)DataBinder.Eval(Container.DataItem, "ThumbnailWidth") %>' Height='<%# (int)DataBinder.Eval(Container.DataItem, "ThumbnailHeight") %>' />
57.
</
a
>
58.
</
li
>
59.
</
ItemTemplate
>
60.
</
asp:Repeater
>
61.
</
ul
>
62.
</
div
>
63.
<
asp:PlaceHolder
ID
=
"socialContainer"
runat
=
"server"
></
asp:PlaceHolder
>
64.
</
div
>
65.
66.
67.
<
div
class
=
"sfproductInfoWrp"
>
68.
<
h1
class
=
"sfproductTitle"
>
69.
<%# Eval("Title") %>
70.
</
h1
>
71.
<
div
class
=
"sfproductPrice"
>
72.
<
sfCatalog:DisplayPriceField
runat
=
"server"
ObjectType
=
"Product"
ObjectId='<%# Eval("Id") %>' />
73.
</
div
>
74.
75.
<
sf:ProductDynamicFields
id
=
"productDynamicFieldsControl"
ProductItem='<%# Page.GetDataItem() %>' runat="server" />
76.
77.
<
div
class
=
"sfproductDescription"
>
78.
<%# Eval("Description") %>
79.
</
div
>
80.
81.
<
div
class
=
"sfproductOptions"
>
82.
<
sf:ProductOptionsControl
id
=
"productOptionsControl"
ProductItem='<%# Page.GetDataItem() %>' runat="server" />
83.
</
div
>
84.
85.
<
div
class
=
"sfProductDocumentsAndFiles"
>
86.
<
sf:ProductDocumentsAndFilesControl
id
=
"productDocumentsAndFilesControl"
ProductItem='<%# Page.GetDataItem() %>' runat="server" />
87.
</
div
>
88.
89.
<
sfOrders:AddToCartWidget
ID
=
"addToCartWidget"
ProductId='<%# Eval("Id") %>' runat="server" />
90.
</
div
>
91.
</
ItemTemplate
>
92.
</
telerik:RadListView
>
93.
</
sf:ConditionalTemplate
>
94.
</
templates
>
95.
</
sf:ConditionalTemplateContainer
>
96.
</
div
>
I'm on Sitefinity 5.2, by the way.
Hey Brandon,
The price has to be displayed/called prior to the documents and files in order for files to show up.
So lines 64/67 have to come after lines 79/81 - or in code:
<
div
class
=
"sfproductPrice"
>
<
sfCatalog:DisplayPriceField
runat
=
"server"
ObjectType
=
"Product"
ObjectId='<%# Eval("Id") %>' />
</
div
>
<
div
class
=
"sfProductDocumentsAndFiles"
>
<
sf:ProductDocumentsAndFilesControl
id
=
"productDocumentsAndFilesControl"
ProductItem='<%# Page.GetDataItem() %>' runat="server" />
</
div
>
this ensures it works.
Or if you feel like playing around further, tweak the code so the ObjectType & ObjectId are set prior to referring to a ProjectItem.
Jochem
Jochem, thank you so much! Reordering the widget template items did the trick. Interesting...