How to create List of Block Data in CMS12

Vote:
 

I have created the block as property and how to create a Collection of Blocks (like PropertyLinkCollection) in one of the page models?

We may be able to implement this using the Generic PropertyList referenced as per documentation. 

Reference Link: https://world.optimizely.com/documentation/developer-guides/CMS/Content/Properties/generic-propertylist/

But this Generic Property List is not recommended by Optimizely CMS on the official website.

Due to the above reason, I am going to use the List of Blocks concept instead of the Generic PropertyList. Can you please provide any links or documents to implement the List of Blocks?

#267283
Nov 24, 2021 9:07
Vote:
 

I'm not sure why that note says they are unsupported. Property Lists were added years ago and I and many many developers have used them extensively without problem. They are definately supported!

#267293
Nov 24, 2021 10:39
Vote:
 

Hi Scott Reed, 

  Thanks for your response. Can we use the List of Blocks in PageData model class in CMS12?

  like below :

    public class HoursBlock : BlockData
    {
        [Display(
          GroupName = SystemTabNames.Content,
          Order = 900,
          Name = "Availability")]
        public virtual string Availability { get; set; }

        [Display(
              GroupName = SystemTabNames.Content,
              Order = 901,
              Name = "Day(s) of the Week")]
        public virtual string DayOfWeek { get; set; }

        [Display(
                  GroupName = SystemTabNames.Content,
                  Order = 902,
                  Name = "Opening Time")]
        public virtual DateTime OpenTime { get; set; }

        [Display(
                  GroupName = SystemTabNames.Content,
                  Order = 903,
                  Name = "Closing Time")]
        public virtual DateTime ClosingTime { get; set; }
    }
    public class Employee: PageData
    {
        [Display(
          GroupName = SystemTabNames.Content,
          Order = 100,
          Name = "Title")]
        [Required]
        public virtual string Title { get; set; }
      
         [Display(
          GroupName = SystemTabNames.Content,
          Order = 200,
          Name = "Standard Hours (limit 7)")]
        public virtual IList<HoursBlock> OpenHours { get; set; }
}
#267295
Edited, Nov 24, 2021 10:49
Vote:
 

Why do you need them as blocks? Can you not just use a model as the https://world.optimizely.com/documentation/developer-guides/CMS/Content/Properties/generic-propertylist/ shows?

#267296
Nov 24, 2021 10:51
Vote:
 

Yes, we can also use model based approach instead of blocks but in my case, the same data going to be used on multiple pages. Due to this reason, I chose the concept of the blocks that means the same instance will be used in the number of pages.

#267297
Edited, Nov 24, 2021 10:56
Vote:
 

I've never seen it work this way for a property list so I'd suggest trying it and see.

Obviously you can just just a content area for a list of blocks and if you're on the newer versions of Opitmizely or have BlockEnhancements installed you can inline edit blocks from the page but you won't see them in page like the gneric list does.

If it doesn't work you could just create an interface inplemented by both your block model and property list model, at least that way you can keep the implementations in check.

#267299
Nov 24, 2021 11:00
Vote:
 

I am using the latest CMS12 version. I didn't understand the part "create an interface implemented by both your block model and property list model".

Can you provide more details or sample snippets on this?

#267300
Nov 24, 2021 11:08
Vote:
 

I just tested and I was able to get your block working in a property list. The problem is it's showing all the extra data that comes from the BlockData base class which makes it unusable.

For the interface comment I was just talking about standard Interface design in C#. We create interfaces to set patterns that classes need to adhere to, such as the below. That way you always make sure you update your interface as your primiary source and then you can just generate the properties on your other models using VS or Code.

 public interface IHoursData
 {
        string Availability { get; set; }

        string DayOfWeek { get; set; }

        DateTime OpenTime { get; set; }

        DateTime ClosingTime { get; set; }
    }
 }
 
 public class HoursBlock : BlockData, IHoursData
    {
        [Display(
          GroupName = SystemTabNames.Content,
          Order = 900,
          Name = "Availability")]
        public virtual string Availability { get; set; }

        [Display(
              GroupName = SystemTabNames.Content,
              Order = 901,
              Name = "Day(s) of the Week")]
        public virtual string DayOfWeek { get; set; }

        [Display(
                  GroupName = SystemTabNames.Content,
                  Order = 902,
                  Name = "Opening Time")]
        public virtual DateTime OpenTime { get; set; }

        [Display(
                  GroupName = SystemTabNames.Content,
                  Order = 903,
                  Name = "Closing Time")]
        public virtual DateTime ClosingTime { get; set; }
    }

    public class HoursPropertyListModel : IHoursData
    {
        [Display(
          GroupName = SystemTabNames.Content,
          Order = 900,
          Name = "Availability")]
        public virtual string Availability { get; set; }

        [Display(
              GroupName = SystemTabNames.Content,
              Order = 901,
              Name = "Day(s) of the Week")]
        public virtual string DayOfWeek { get; set; }

        [Display(
                  GroupName = SystemTabNames.Content,
                  Order = 902,
                  Name = "Opening Time")]
        public virtual DateTime OpenTime { get; set; }

        [Display(
                  GroupName = SystemTabNames.Content,
                  Order = 903,
                  Name = "Closing Time")]
        public virtual DateTime ClosingTime { get; set; }
    }
#267301
Nov 24, 2021 11:19
Vote:
 

Great, Scott Reed for providing the code snippet. May I know what is the purpose of the HoursPropertyListModel class? 

Shall I declare the List block like below:

 public class Employee: PageData
 {
        [Display(
          GroupName = SystemTabNames.Content,
          Order = 100,
          Name = "Title")]
        [Required]
        public virtual string Title { get; set; }
      
         [Display(
          GroupName = SystemTabNames.Content,
          Order = 200,
          Name = "Standard Hours (limit 7)")]
        public virtual IList<HoursBlock> OpenHours { get; set; }
}

I am just curious to see the output in CMS Editor for list block types. Please share a screenshot if it's handy.

#267311
Edited, Nov 24, 2021 13:37
Vote:
 

The HoursPropertyListModel is if you want to use an interface so that both a model for Blocks and a model for PropertyLists can be kept the same. It's just standard C# and OOP

To get your block working as a model you need to make sure two things. 

1. You have your property definition class so it can be allowed for Property Lists. Add this as a separate C# file

    [PropertyDefinitionTypePlugIn]
    public class HoursBlockPropertyListDefinition : PropertyList<HoursBlock>
    {
    }

2. You have added the decorator above your OpenHours property to allow it to work

[EditorDescriptor(EditorDescriptorType = typeof(CollectionEditorDescriptor<HoursBlock>))]

As shown in the link https://world.optimizely.com/documentation/developer-guides/CMS/Content/Properties/generic-propertylist/  these are always required to configure your model on the property.

#267312
Nov 24, 2021 14:00
Vote:
 

Hi Scott Reed, Thanks for clarifying my doubts.

I implemented it using List Block in the sample project and worked as expected but a lot of extra properties are showing on the Item Details dialogbox.

How to hide all extra properties in the Item Details Page.  

Refer image for output of Item Details Dialog box: https://imgur.com/a/AqNjMe

#267320
Nov 24, 2021 15:15
Vote:
 

Yes that's what I was saying when I said a few posts back "The problem is it's showing all the extra data that comes from the BlockData base class which makes it unusable." when I tried it too.

I don't think there's a way to specifically hide properties for only the Propery List showing as it's designed to auto show the properties because you're supposed to use a specific model not a block.

As this point I would personally say you're going way too in depth to try and protect yourself from having a model and the block.

Just create both with the interface as I mentioned so you can keep them aligned, the small duplication of property declaration code is miniscule compared to trying to enginerr a solution to dynamically hide and show property based on context. 

#267321
Nov 24, 2021 15:19
Vote:
 

thanks, Scott Reed for your detailed explanation of my problem. I will create both with an interface as you mentioned.

#267323
Nov 24, 2021 15:30
Vote:
 

I would recommend using IList<ContentReference> instead. If you only want to allow a specific block type, you can decorate the property with the AllowedTypes attribute. The UI has better inline-editing nowadays.

We have full support for lists of value types, such as IList<string> and IList<int>. Use complex types with caution, because there is no built-in support for migration when you change the type. This has to be implemented in a custom serializer.

#267373
Nov 25, 2021 12:58
Scott Reed - Nov 25, 2021 13:07
If he wants to move away from editing a collection of data and mange them as blocks via editing/quick editing then yes Content Areas (which I mentioned) or IList could be used but as far as he had said I believe he wanted the generic list editing experience
Johan Petersson - Nov 25, 2021 13:17
With the new inline-editing of content in ContentArea and IList ContentReference the experience is pretty much the same as for IList ComplexType, difference being that not all properties are displayed in the "list view". The inline-editing will keep improving as well, especially for "local" block store in the "For this page" folder.

Great that you haven't had any issues with complex list types. But that's no guarantee though :)
Scott Reed - Nov 25, 2021 13:22
There seems to be a problem where comments are being cut off but I saw you're reply in the email notification. Yes I agree it's getting better, I was using the inline editing feature from the first time it was in BlockEnhancements and have been pushing it but there's still an advantage if you want a collection of data that you visibly want to see rather than blocks and having to inline edit them to see the data in the properties view. Usability wise there's still plenty of times I would chose to using generic lists over an IList of content reference or ContentArea. And of course, there are many things in the Optimizely platform that you have to understand or you can get issues, there's no guarantees with anything but with a small amount of awareness you can handle it
Johan Petersson - Nov 25, 2021 13:27
Hmmm yeah irritating that comments gets cut off after a reserved character.

With the improvements coming, the use for complex list types shouldn't be necessary. I'm not saying we should or would, but there might be a case for obsoleting complex list types after these improvements.
Scott Reed - Nov 25, 2021 13:29
Nice, that's good. I knew there were some CMS changes coming but if this makes generic lists not needed for a better editing experience I'm all for it :-)
Vijay - Nov 25, 2021 13:31
thanks to both Johan Petersson & Scott Reed for your detailed explanation on this.
Johan Petersson - Nov 25, 2021 13:33
... and to not worry anybody, by obsoleting I don't mean that we would remove the functionality. At least not without providing an easy upgrade path.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.