diff --git a/helix/principles/templates/references.rst b/helix/principles/templates/references.rst index 6ebb8e1..85a75a8 100644 --- a/helix/principles/templates/references.rst +++ b/helix/principles/templates/references.rst @@ -12,77 +12,80 @@ field names if needed. Furthermore, hardcoded GUIDs tend to stick out in code and views and therefore makes it easier to detect and avoid implicit dependencies to templates and fields. -Define constants for a module’s templates in a single struct named -Templates. This struct is located in the root namespace for the module. +Define constants for a module’s templates in a single static class named +``Templates``. This static class is located in the root namespace for the module. This makes it easy to explicitly reference a template in the business -logic or views and makes it easier to discover references to a template -or field. The conventions define this as structs to clearly signal the -Templates type’s unique function as a constants holder only. +logic or views of the module and makes it easier to discover references to a template +or field. The conventions define this as a static class to clearly signal the +``Templates`` type's unique function as a constants holder only, following the +`conventions for Constants in the Microsoft C# Programming Guide `__. -Each Templates struct should have a nested struct for each template -which each contains an ID member and a nested struct, Fields, which +The ``Templates`` static class should have a nested static class for each template +which each contains an ID member and a nested static class, Fields, which contains all fields in the template. -.. admonition:: Habitat Example +.. admonition:: Sitecore Helix Examples - The following shows the Templates struct for - Sitecore.Feature.Navigation: + The following shows the ``Templates`` static class for the *Feature / Basic Content* module in Helix Basic Company. .. code-block:: c# - namespace Sitecore.Feature.Navigation + namespace BasicCompany.Feature.BasicContent { - using Sitecore.Data; - - public struct Templates + public static class Templates { - public struct NavigationRoot + public static class PromoCard { - public static readonly ID ID = new ID("{F9F4FC05-98D0-4C62-860F-F08AE7F0EE25}"); + public static class Fields + { + public static readonly ID Link = new ID("{B788E8BC-E944-4A2B-A4BE-3424643D322B}"); + public static readonly ID Image = new ID("{21249F44-5F0F-4CFA-9474-8D72930D6575}"); + public static readonly ID Headline = new ID("{4F73C02B-93CC-4C96-B9FF-9D0D8E853ED6}"); + public static readonly ID Text = new ID("{13EB8DCA-281D-4E75-B6E1-701CA719BCD1}"); + } } - public struct Navigable + public static class SectionHeader { - public static readonly ID ID = new ID("{A1CBA309-D22B-46D5-80F8-2972C185363F}"); - - public struct Fields + public static class Fields { - public static readonly ID ShowInNavigation = new ID("{5585A30D-B115-4753-93CE-422C3455DEB2}"); - public static readonly ID NavigationTitle = new ID("{1B483E91-D8C4-4D19-BA03-462074B55936}"); + public static readonly ID Text = new ID("{59D24D0A-F955-4988-B26F-92039B4DF8BD}"); } } - public struct Link + public static class HeroBanner { - public static readonly ID ID = new ID("{A16B74E9-01B8-439C-B44E-42B3FB2EE14B}"); - - public struct Fields + public static class Fields { - public static readonly ID Link = new ID("{FE71C30E-F07D-4052-8594-C3028CD76E1F}"); + public static readonly ID Title = new ID("{5179186C-B95E-4E97-95AB-7958721A9AEB}"); + public static readonly ID Subtitle = new ID("{89B0A8ED-0EE8-4512-B518-AB2C4C2A0B9E}"); + public static readonly ID Image = new ID("{B5F61442-FF0F-46A5-90A8-D6D387DE24A0}"); } } - public struct LinkMenuItem + public static class AccordionItem { - public static readonly ID ID = new ID("{18BAF6B0-E0D6-4CCE-9184-A4849343E7E4}"); - - public struct Fields + public static class Fields { - public static readonly ID Icon = new ID("{2C24649E-4460-4114-B026-886CFBE1A96D}"); - public static readonly ID DividerBefore = new ID("{4231CD60-47C1-42AD-B838-0A6F8F1C4CFB}"); + public static readonly ID Title = new ID("{5718E787-142B-41D9-B5A1-0B18F45B8236}"); + public static readonly ID Content = new ID("{45EFE66E-5AD2-4F1D-BAD5-FDF281688681}"); } } } } -A templates class should never define constants for templates that are -not created in the module itself. If a module needs to reference a -template or field in another module, it should reference the Templates -struct in that module. +A ``Templates`` class should never define constants for templates that are +not created in the module itself. In cases where Sitecore Helix conventions +allow a module to reference another (e.g. *Feature* to *Foundation*, or *Project* +to *Feature*), if a module needs to reference a template or field in that module, +it should reference the Templates struct in that module. Or better yet, that +module could expose an extension method or other means of consuming that template, +to avoid directly referencing the ID constants, as this dependency could make future +refactoring more difficult. The practice of referencing different fields across modules by their -shared name – an equivalence to *duck typing* – is discouraged. +shared name – an equivalence to *duck typing* – is strongly discouraged. .. note:: @@ -107,9 +110,33 @@ inheritance object-oriented programming, it is important that, when querying an item’s template, you not use the *equals* operator but rather an *is* operator. -.. admonition:: Habitat Example +.. admonition:: Sitecore Helix Examples + + The *is* operator in the Sitecore Item API is the `DescendsFrom` + method on the `Item` class, which accepts a Template ID. This allows + you to determine whether an item directly or indirectly inherits from a + template. You can see this used in Helix Basic Company's `HeaderBuilder` + class: + + .. code-block:: c# + + // Collect home/root item and its children which are navigable + var items = new List { navigationRoot }; + items.AddRange(navigationRoot.Children.Where(item => item.DescendsFrom(Templates.NavigationItem.Id))); + + When querying for a specific base template via Content Search query, you + will need to enable the ``_templates`` computed field. See the + ``Sitecore.ContentSearch.[SearchProvider].DefaultIndexConfiguration.AllTemplates.config.example`` + example patches in your Sitecore installation, or the ``Feature.Products.ContentSearch.config`` + in Helix Basic Company. + + With this computed field available, you can map and query it in Content Search code: + + .. code-block:: c# - The *is* operator is not native to Sitecore items and templates. - Sitecore Habitat introduces the IsDerived extension method for the Item - class. This method is located in the - Sitecore.Foundation.SitecoreExtensions.Extensions.ItemExtensions class. \ No newline at end of file + var results = context.GetQueryable() + .Where(product => product.Paths.Contains(parent.ID) && product.Templates.Contains(Templates.Product.Id)) + .Select(x => new { + Uri = x.UniqueId, + Database = Factory.GetDatabase(x.UniqueId.DatabaseName) + }).ToList(); \ No newline at end of file