Wicket Page with a list of Panels - list

I'm working on a web application using Apache Wicket and I have three types of page that are basically a numbered list. The difference between each is how the items in the list are displayed. (i.e. one has a header line and a paragraph, another just has the paragraph). Eventually, the data will come from a database, but that is not available at the moment.
I think I can do this by creating a Page that displays a RepeatingView that gets its items from an ArrayList of Panels. I would create a different Panel for each type of list item. Then I could extend the aforementioned Page to three subclasses, one for each specific type of Panels I want. Am I on the right track, or is there a better way to do this?

I find RepeatingView to be very flexible with this sort of thing and you shouldn't require three separate pages. It only expects a component to be added to the repeater, not what kind of component. As long as you keep your Wicket IDs consistent, you can even mix components that come with their own markup (e.g. Panel/Fragment).
I also discourage you from using a List of Panels. It just makes good programming sense for the list to contain your data and then add the appropriate view container based on some flag.
So, markup like this:
<div wicket:id="repeater">
<div wicket:id="listItem" />
</div>
Works with something like:
RepeatingView rv = new RepeatingView("repeater");
for (DataObject o : dataList) {
// You can probably add to the rv directly, but this is the common usage
WebMarkupContainer c = new WebMarkupContainer(rv.newChildId());
rv.add(c);
if (shortVersion)
c.add(new ShortPanel("listItem", new Model<DataObject>(o)));
else
c.add(new LongPanel("listItem", new Model<DataObject>(o)));
}
Instead of providing a List of Panels to your page, you provide the same list of Data from the database and then add different panels based on the current view.
In the end, you have one page (with a flag for view type) and different panels (or fragments) for how your data should look according to each view type.

I don't think you'll have to subclass your Page. As far as I can see, this one doesn't change at all. All the changes are within the panels. So basically all you need to do is to provide your repeating-view with different lists of panels. You wouldn't even need to create different classes for these if the differences are as small as presenting a headline or not. Just set the headline to an empty string and set it to invisible...
Basically yes, you're on one of the right tracks, maybe not the one I'd choose but yours will work too...

Related

List of News Articles In Sitecore (Best Approach?)

I am creating a Sitecore MVC site for a client and I need to create page that will list news articles for the company.
So far, I have created items that use a shared data template called “Article,” and I also have a sublayout (a view rendering) called “Article” that will display these items.
For the list itself, my plan was to create another component (a sublayout) call “News_List”, and to put a placeholder in it called “List”.
My question is this: can I allow the author to insert articles (e.g., N items of type “Article”) into this placeholder via the page editor?
Will SC allow you to insert multiple instances of the same component into a placeholder? Will this break anything?
I believe this is a pretty common question but I have not found a definitive answer. Thanks in advance…!
You can insert as many components (of the same type) in your placeholder as you want.. Just make sure to put the placeholder settings correctly and give it a decent name (not just "list" ;))
But are you sure you want to do this? Your editors will manually need to create a list of components for each article they want to add on the page. Doesn't sound to be very user (editor) friendly.. Maybe you should consider creating a list component that can get a list of articles as a datasource and show those. Or even select them automatically (but that might be not according to your business case)..
Yes, authors can add multiple instances of the same component into a single placeholder.
Assuming that the code of the component doesn't do any stupid things it's absolutely ok to do this.

Specify order of slides in carousel?

Is there a way to control the order of slides displayed to users in a carousel from the Experience Editor perspective? (or even the Content Editor)
Basically, based on the user that has been identified or not identified, I would like to display a different slide as the first slide of the carousel. All the other slides would still be present, just in a different, specified order.
Is there a way to accomplish this via rules or should I look at having to create separate datasources that have the different slide orders already specified?
TL;DR
Personalization can do three things:
vary a datasource for a rendering
vary a rendering (use another rendering basically)
hide a rendering.
I guess the question you need to answer is whether what you need can be accomplished by doing either one of these actions.
If you've used nested structures to represent your carousel (like we do in SCORE, you can see how it looks like here or here) it's not hard to show/hide certain panels based on personalization conditions and thus reorder the carousel. Depending on how exactly it looks on the published site you may only need to repoint datasources. Either way, it's personalization out of the box and your content structures working nicely together.
If you've used a (variation of a) MultiList field to represent a list of your panels with panels themselves being items somewhere in the shared content area it's not something personalization engine can change based on a condition. Changing a field value is, unfortunately, not on the menu. I am sure you can code around it thanks to Sitecore being so open and flexible but I am not sure you can make it seamless (e.g. variations preview in Page Editor).
Rendering parameters is also not something you can change but if yours are static and defined on the rendering definition item (as opposed to being supplied when component is bound to the placeholder and thus recorded inside the presentation details) you can get away with having two definition items for your carousel component (same code behind it) and picking the right one based on the personalization condition.
Hope it helps.

Best practice for accessing Sitecore Items via code

Quite new to Sitecore and would like to understand the best way to access sitecore items. I've seen couple of ways:
Create Page ID field and get all items for given template and folder. Then do linq query on page ID.
Store all Page ID (Sitecore Item ID) on Constants file. Use this to query Sitecore using GetItem(itemID) API.
Could someone please suggest what's the best practice. Either way, I can see that there will be huge Constants file containing either custom Page ID or Sitecore Item ID.
My worry is do we really need to manage this Constants file or is there an elegant way to query CMS contents for given Page.
Thanks.
Approach 1 seems a bit odd. I don't really see why you would get a collection of items first when you already have the ID, but maybe I've misunderstood what you're saying.
I think a combination of 2 things you mention is best.
Constants classes are good for "landmark" items that will always definitely be there, so its fine for the GUID to be in code.
Some of these landmark items can be "configuraton items" that have fields containing the IDs of other items (These fields might have names like "Templates allowed in search"). This approach allows some flexibility for change by Sitecore users as the site evolves.
If you're concerned about the management of a constants file, I have to wonder how many items you need to access by ID. Sitecore items have properties like Parent and Children. You can also find items by template type etc.
This approach works well for me. I certainly don't think there is a more elegant way of getting strongly typed references to Sitecore items.
Personally, I prefer not to use constants files. What happens if your client or one of your developers deletes one of those items and creates a new one? One of the fundamental principles of Sitecore is that items can be added and removed by users who are not necessarily "technical" personnel.
Sitecore provides "Insert Options" so that you can specify what types of items can be added to each folder, and also grants the ability to protect certain items from deletion, via Roles and User Permissions. What does this mean conceptually? It means that Sitecore is set up such that the system architects/developers can create a structure that is not to be violated, while the content editors can add or remove content within that structure. In other words, Sitecore is designed to provide a framework in which the items can change but the location of each type of item is pre-determined.
As such, I suggest that you use the Custom Item Generator module available in the Sitecore Marketplace (free). CIG generates C# class representations (models) of your templates, and makes all fields into properties (I don't want to get too off-topic, but this is an awesome feature of CIG, especially when working with newer developers). You can add your own methods to your CIG classes for getting children of a particular type. For example, on a site in which the Profile Page is a direct child of the Homepage the following method could be added to the CIG HomepageItem.instance.cs file's HomepageItem partial class:
...
public partial class HomepageItem
{
public ProfilePageItem GetProfilePage()
{
//note that .IsOfType(...) is pseudo-code and not a real method, but I do
// suggest that you define an extension for it
return InnerItem.Children.FirstOrDefault(i => i.IsOfType(ProfilePageItem.TemplateId));
}
}
Be sure that you are assigning Insert Options to restrict the types of items that can be added as children to each item you make (add them on the Standard Values and not on the individual content items). I also suggest that you make a separate Template that inherits from Common/Folder for every folder that you use in the content tree. This way you can use CIG for your entire structure, via:
...in your Globals Item's CIG class...
public partial class GlobalsItem
{
public SlidesFolderItem GetSlidesFolder()
{
return InnerItem.Children.FirstOrDefault(i => i.IsOfType(SlidesFolderItem.TemplateId));
}
}
...in your Slides Folder Item's CIG class...
public partial class SlidesFolderItem
{
public IEnumerable<SlideItem> GetSlides()
{
return InnerItem.Children.Where(i => i.IsOfType(SlideItem.TemplateId));
}
}
and then you can get your Slide items via:
...
var slidesFolder = globals.GetSlidesFolder();
var slides = slidesFolder != null ? slidesFolder.GetSlides() : null;
Remember that CIG, Insert Options, and templates for each type of folder will enable you to create an iron-clad structure for your site that will not break if content editors make unexpected changes like replacing items.
Let me know if you have any questions on this. Good luck, and Happy Coding! :)

Multiple item templates in Grid App

I'm developing a Windows Store application based on the Grid application template. Upon creating a new project, there is some sample data generated for the application. There are only three pages in the app: home, grouped items, and item details.
I'm wondering whether it's possible to have different templates for item details, and if so, how.
For instance, I have a group containing a list of smartphones and another group containing a list of printers. In the smartphones item details template, I'd probably have fields such as "Memory card", "Speakerphone", and "Operating system", whereas in the printers item details template I'd have fields such as "Speed", "Accepted cartridges", and "Paper sizes".
How should I go about adding item detail templates and using the correct one depending on which item is viewed? I've looked at http://babaandthepigman.wordpress.com/2012/02/08/datatemplateselector-winrt/ but that seems to be for XAML applications only. I'm not using XAML/VB/C++/C#, but JavaScript and HTML5.
To be clear the three pages in the grid project template are groupedItems (the "hub"), groupDetail (the "section"), and itemDetail (the "detail"). I actually wish they would have named those pages "hub", "section", and "detail".
If you're talking about having multiple item templates so that item tiles on the hub (groupedItems) page look different depending on the item type, then the easiest way is to provide the multiple item templates (WinJS.Binding.Template) in the HTML and then write a custom template selection function. It's not that difficult. You can see an example if you look at my codeSHOW app (codeshow.codeplex.com)... see the home.js page. The source is online, so you can see that page here.
If you're talking about having multiple detail (itemDetail) pages so that when a user clicks on a certain item from the hub, they might be taken to a whole page of information about a phone versus a printer, then that's simply a matter of having multiple pages and being intelligent about which page you navigate to. If the user clicks on a phone from the hub, then you navigate to /pages/phone/phone.html. If they click on a printer then you navigate to /pages/printer/printer.html.
Finally, if your entities (i.e. phones and printers) are similar enough, then you may want to keep a single page to represent them, and just make that page smart enough to modify its template for the right item. In that case, you can create two templates on the page (WinJS.Binding.Template again) and when the entity is passed in to the page (the 'options' part of ready(element,options)), you just inspect it and look at the entity type (i.e. phone or printer) and then render the data into the right template. The Binding and Templating and Fragments and Pages demos on codeSHOW may be helpful there.
If you want more help, you can schedule some 1 on 1 time with a Microsoft Developer Evangelist at usdpe.ohours.org. Have fun!

Sitecore Content Tree Architecture

Let's say there exists a presentational component in a project that renders an unordered list (called ListRenderer, perhaps.) We have a couple options of supplying data to any given ListRenderer on a page:
Have a TreeList (or TreeListEx) field on the content item, and have ListRenderer read from it.
Supply a DataSource (or other Parameter) to the ListRenderer via the presentation details.
I usually avoid #1 in my projects because it binds Sublayouts to templates, which gets quite messy. If you go down that path, eventually you'll have fields to support every potential sublayout in your project.
So my solutions tend toward option #2, which gets rid of that problem. It does, however, come with its own bag of questions. Where do I put these various "Lists" for a given ListRenderer to use? To maximize reuse and sharing, I usually create a components directory near the site root that contains all these types of things, if I predict the Lists will be shared. This seems less findable and harder to use for the content author, who suddenly have no idea where the source for their ListRenderer is unless they know how to crack open the presentation details (which is slightly advanced for my average user).
If I feel like Lists won't be shared, and are very specific to the page, I'll put them directly underneath the item in question. This has a tendency to muddle up the content tree, though, and any dynamically generated navigation sublayout then has to check for whether or not an item is an actual page before it generates the link to it. The more I work in Sitecore, the less I use this approach, but it seems easier for the content author. There is much easier access to information when you use this approach.
Is there any industry-accepted way of approaching this problem? It happens in projects all the time, and in my head I struggle to balance technical and content authorship concerns in situations like these.
Great question. I've used all the techniques you mentioned, depending on the audience and specifics of the project. The problem is that, as with all things Sitecore, they are all valid ways of achieving the same goal and you will struggle to find one answer that will work in every situation.
I almost always use #2 as well, but some content author retraining maybe necessary and make sure you add in restrictions to what the content author is able to select as a target. I have (within the same project) structured the items near the root (in a shared content folder) and under the item in question, depending on what I felt would provide the best context.
Also, if other child pages would exist below the item as well as the list items, then I would put the list items in a separate folder (with a common "list items" icon") and re-order it to be the first item for separation and clarity.
If you want to use any kind of personalization and DMS then you will need the ability to switch out the datasource anyway so you shouldn't hard code locations.
You might also (if you have not already) want to consider using:
Convert Data Source Paths to IDs Using the Sitecore ASP.NET CMS
- Useful if you need to restructure your content at a later date
Queryable Datasource Locations
- Useful for multi-site situations when you need to make clones, or setting as the default datasource value in Standard Values when the lists are directly below the item but gives you the flexibility to change it.
I prefer using querable datasources personally, I find the xpath syntax more logical.
As Mark has commented, there is no real industry standard.
I feel like this is something that needs improvement.
Especially when you are using the DataSource option, things become less transparent to the editors and as the size of the site grows, so does the complexity.
All I can tell you is how I would do it, which is most likely much like how you are doing it.
1) For overview pages like news, events and faq items, I will put the items underneath the overview item and use the NewsMover shared source module to auto-create a hierarchy.
2) I will create a Global site that contains items that are shared across sites or pages. DataSource items for components will be put in here.
3) For components that are present on the standard values, I will add a list field to the template (for example, when you display related items on a content page)
Most often it's a logical choice and sometimes it's just a matter of taste.
I'd like to add that I've written a blog post on how to have datasource items created automatically for components that are set on standard values. That might help you if you are using those.
Edit:
"I usually avoid #1 in my projects because it binds Sublayouts to templates, which gets quite messy. If you go down that path, eventually you'll have fields to support every potential sublayout in your project."
Today I've blogged about a method of hiding fields and sections in the content editor if there is no sublayout set on the item that requires those fields, which helps to prevent the mess of having a lot of unused fields on your items.