Skip to content

Editor templates

Simon Yohannes edited this page Nov 15, 2023 · 25 revisions

built in editor templates

you can find the built in editor templates in the PuckWeb/areas/admin/views/shared/editortemplates folder. there are templates for the common types such as boolean, string, datetime but also an object template. for most of your properties, you won't need to specify a UIHint and the editor template will be chosen based on the Type of your property, so string properties will automatically use the String template, datetime the DateTime template and so on. we'll go into the more advanced templates here.

note: while in these examples you'll see the UIHint typed out manually, it's more convenient to use the EditorTemplates class which has string constants you can use rather than typing out the editor template name.

jump to

Content Picker

this template is used with a List<puck.core.Models.PuckReference> model and is used to select content nodes. you may add a List<PuckReference> property to your Homepage ViewModel for example, to select RelatedContent:

public class Homepage:BaseModel
    {
        [Display(Name="Related Content")]
        [UIHint("ContentPicker")]
        [ContentPickerEditorSettings(MaxPick =5,Types = new Type[] {typeof(Page),typeof(Section) })]
        public List<PuckReference> RelatedContent { get; set; }
    }

the PuckReference class has some extension methods for querying data in the puck.core.Helpers namespace which allow you to retrieve content. there's a List<T> GetAll<T> method and a T Get<T> method which allow you to retrieve the picked content.

how it works is that PuckReference has two properties, Id (which is a guid) and Variant (which is the language of the content) and this information is used to query content.

the Content Picker has configurable settings which can be added by using the ContentPickerEditorSettings attribute as in the example above or by going to "Settings -> Editor Parameters" and adding an Content Picker Editor Settings entry.

List Editor

the ListEditor is very useful for editing List<T> properties. here's an example of using list editor in a ViewModel:

public class Page:BaseModel
    {
        [Display(ShortName ="input",GroupName ="Content")]
        [UIHint("ListEditor")]
        public List<string> Names { get; set; }

        [Display(ShortName = "[name$='Name']",GroupName ="Content")]
        [UIHint(EditorTemplates.ListEditor)]
        public List<ComplexModel> Test { get; set; }
    }

in the code above, there are two properties which use the ListEditor UIHint, one is editing a list of strings and the other is editing a list of some complex type. the display attribute ShortName option is used to provide a jQuery selector for the row title in the edit screen. the first example uses the selector "input" which means it will grab the row title for a particular row from the value of the first input element of that row. the second example uses the ShortName selector of "[name$='Name']" which means it will get the row title from the first element with the name attribute ending with "Name". this selector is more specific than the previous "input" selector because it's for a list of complex type rather than a list of string - meaning it will contain more than a single input per row which means the selector needs to be more specific. if no ShortName selector is provided, rows will be titled "item 1", "item 2" .. and so on.

the GroupName option specifies which tab this field will be displayed in, on the edit screen. you can also specify tabs for your ViewModel in the settings section of the backoffice but if any GroupName is specified in the ViewModel code, it will take precedence over any tabs you setup using the settings interface.

you can override the Editor Template which is used by using the settings attribute puck.core.Models.EditorSettings.Attributes.ListEditorSettingsAttribute. for example, for lists of string by default the String template will be used (which uses an input field with type text) but you could override it to the TextArea or rte (rich text editor) templates.

Image Picker

this editor template works much like Content Picker but is used to select instances of the ImageVM ViewModel, whereas Content Picker is used to pick any type of content. unlike the Content Picker, it gives you an image preview while you're selecting. the model for this template is the same as the Content Picker. here's an example of a ViewModel using the Image Picker:

public class Homepage:BaseModel
    {
        [Display(Name="Image Gallery")]
        [UIHint(EditorTemplates.ImagePicker)]
        [ImagePickerEditorSettings(MaxPick = 2)]
        public List<PuckReference> ImageGallery { get; set; }
    }

the Image Picker has configurable settings which can be added by attribute (as in the example above) or by going to "Settings -> Editor Parameters" and adding an Image Picker Editor Settings entry.

also note the use of the EditorTemplates class which contains constants for the editor template names, making it easier to specify the UIHint.

Map

the GeoPosition editor is used for picking Longitude and Latitude values from a google map. the model for this editor template is puck.core.Models.GeoPosition and this type is indexed in lucene as a spatial type for geo searches. since the model type and editor template name are the same (both GeoPosition), you don't need to actually specify the UIHint like is being done below. you can specify your Google Maps API Key using the GMapsKey appSetting.

public class Homepage:BaseModel
    {
        [UIHint(EditorTemplates.Map)]
        [Display(GroupName ="Map")]
        public GeoPosition Location { get; set; }                
    }

Rich text editor

the RichText editor template is used for rich text content. the model for this editor template is string and it uses the "tiny mce" plugin.

public class Homepage:BaseModel
    {
        [Display(Name = "Main Content")]
        [UIHint(EditorTemplates.RichText)]
        [RichTextEditorSettings(Width = "100%", Height = "800px")]
        public string MainContent { get; set; }
    }

use the settings attribute puck.core.Models.EditorSettings.Attributes.RichTextEditorSettings, to specify a width and/or a height, or defaults will be used.

Tags

the tags editor works on a model of List<string> and allows you to enter tags with auto complete/suggestions based on previously entered tags.

public class Homepage:BaseModel
    {
        [UIHint(EditorTemplates.Tags)]
        public List<string> Tags { get; set; }
    }

you can also use TagsEditorSettings to specify the category of your tags. then you will only get suggestions from other tags in the same category. as with some of the other editor templates, their settings can either be set as attributes on the ViewModel property, or in the Backoffice on the "Settings->Editor Parameters" page.

TextArea

standard text area, use the settings attribute puck.core.Models.EditorSettings.Attributes.TextAreaEditorSettings, to specify a width and/or a height, or defaults will be used.

public class Homepage:BaseModel
    {
        [TextAreaEditorSettings(Width ="100%",Height ="600px")]
        [UIHint(EditorTemplates.TextArea)]
        public string Text { get; set; }
    }

Select List and Multi Select List

with these editors, you can specify the values used in the drop downs/multi selects by using the puck.core.Models.EditorSettings.Attributes.SelectListSettings

public class Homepage:BaseModel
    {
        [Display(GroupName ="Content")]
        [UIHint(EditorTemplates.SelectList)]
        [SelectListSettings(Values =new string[] {"Si:Simon","John","Andy:Andrew"})]
        public string Names { get; set; }

        [Display(GroupName = "Content")]
        [UIHint(EditorTemplates.MultiSelectList)]
        [SelectListSettings(Values = new string[] { "Si:Simon","John","Andy:Andrew" })]
        public List<string> MultipleNames { get; set; }
    }

By default, the character : is used to separate Label and Value for the select list values, e.g. Si:Simon - Si being the Label and Simon being the Value. if you only specify a Label, like John, it will also be used as the Value. if you want to use a different separator, you can specify a separator in the SelectListSettings attribute. you can also specify the default label, which has a default value of - Select -.

There is also an option to get values from the JSON app settings file.

[SelectListSettings(FromJSONSection = "Cities")]
[Display(GroupName = "Selects")]
[UIHint(EditorTemplates.SelectList)]
public List<string> Cities { get; set; }

the appSettings.json, Cities section then looks like this:

"Cities": ["london:uk","paris:france","tokyo:japan"],

SelectList supports numbers as well as strings:

public class Homepage:BaseModel
{
    [Display(GroupName ="Content")]
    [UIHint(EditorTemplates.SelectList)]
    [SelectListSettings(Values =new string[] {"Twenty:20","Thirty:30","Forty:40"})]
    public int Age { get; set; }
}

as you can see above, the property is of type int. the values set in the settings attribute need to be castable to int though, or you won't be able to select them.

MultiSelectList doesn't support anything other than string collections (Lists/Arrays/IEnumerables of string).