Home » Официальная поддержка списка свойств | Сообщество разработчиков Optimizely

Официальная поддержка списка свойств | Сообщество разработчиков Optimizely

Введение

До сих пор пользователи могли сохранять свойства списка тремя способами:

Все эти подходы имели свои проблемы и ограничения.

Очевидным ограничением первого было то, что он мог работать только с очень простыми типами. С другой стороны, это обеспечило приятный опыт редактирования благодаря встроенному редактору значений и автосохранению.

Следующий был гораздо более мощным, поскольку позволял пользователю использовать любой тип POCO, а затем отображать список в табличном виде:

755

и позволить пользователю редактировать каждый элемент из диалогового окна:

757

Однако у этого подхода также было несколько проблем:

  • Значения свойств сериализуются в JSON и сохраняются в виде простой строки в базе данных.
  • Постоянные ссылки не проверяются
  • Некоторые вещи, такие как импорт/экспорт, значения по умолчанию, пользовательские расширители метаданных, необходимо реализовать вручную.

Наконец, подход с использованием ContentArea или списка ContentReference теоретически решает все эти проблемы, потому что редактор может в любом случае определить элемент списка блокировки и может использовать существующие свойства, однако каждый элемент списка является отдельным экземпляром IContent, который имеет свой собственный издательский жизненный цикл. Кроме того, он также проходит тот же процесс утверждения, может быть включен в проект в качестве элемента проекта и т. д.

Из-за того, что каждый блок представляет собой отдельный IContent, невозможно легко просмотреть изменения или опубликовать все элементы сразу.

Было несколько попыток решить эту проблему, одна из них — пакет Block Enhancements Labs:

Новое свойство списка

В EPiServer.CMS 12.18.0 мы выпускаем совершенно новое свойство списка, которое решает все проблемы, описанные выше.

Добавить свойство списка так же просто, как:

public virtual IList Contacts { get; set; }

Где ContactBlock можно определить следующим образом:

[ContentType(AvailableInEditMode = false, GUID = "38d57768-e09e-4da9-90df-54c73c61b270")]  
public class ContactBlock : BlockData  
{  
   //block properties  
}

Здесь важен тот факт, что каждый экземпляр ContactBlock не будет отдельным элементом содержимого, а будет храниться внутри своего родителя.

Этот факт имеет несколько значений:

  • Редактору больше не нужно переключать контекст, чтобы редактировать эти встроенные блоки.
  • Встроенные блоки не имеют жизненного цикла публикации, что означает, что при изменении любого элемента списка пользователь-редактор увидит новую версию текущего создаваемого контента.
  • Элементы списка будут наследовать последовательность утверждения от своего родителя, это родительский контент, который должен быть проверен и утвержден.
  • Элементы списка не будут включены в проекты, только их родительское содержимое в целом.

Редактор такого списка блокировки контактов будет выглядеть так:

Конечно, возможность сделать блоки встроенными является основным вариантом использования нового списка. однако он способен хранить внутри любой тип свойства.

Пользователи по-прежнему могут использовать основные типы, такие как:

public virtual IList Numbers { get; set; }

public virtual IList Strings { get; set; }

public virtual IList Dates { get; set; }

Но также можно использовать и более сложные типы:

public virtual IList XHtmlStrings { get; set; }

Или, например, создайте список изображений или видео:

[ListItemUIHint(UIHint.Image)]
public virtual IEnumerable Images { get; set; }

Который будет отображаться следующим образом:

Обратите внимание, что свойство помечено новым атрибутом ListItemUIHintAttribute, который работает так же, как обычный UIHint, но применяется к общему типу элемента списка.

Таким образом, мы указываем свойству List использовать UIHint.Image для отдельных элементов.

По-прежнему можно использовать UIHint(“YourCustomListEditor”), если у вас есть собственный редактор.

Рендеринг

Никаких специальных атрибутов или методов не требуется для отображения списка любых типов свойств.

Единственное, что необходимо, — предоставить шаблон отображения для одного элемента, а CMS сделает все остальное, заключив каждый элемент в элемент списка.

public virtual IList Blocks { get; set; }

Вам просто нужно будет предоставить EditorialBlock.cshtml, который может выглядеть так:

@model EditorialBlock

x.MainBody)> @Html.DisplayFor(x => Model.MainBody)

И для отображения свойства Blocks на странице вы можете использовать любой пакет HtmlHelpers:

@model MyPage

@Html.PropertyFor(x => x.EditorialBlocks)

Или новый пакет TagHelpers:

@model MyPage

Миграция

Модель данных за кулисами сильно отличается от предыдущих реализаций, которые всегда основывались на какой-то сериализации JSON.

Не существует автоматического способа перехода со старой модели на новую, и все миграции могут отличаться от случая к случаю, но давайте представим такой гипотетический сценарий:

Допустим, у нас есть страница MyPage.cs с одним свойством внутри:

public class MyPage : PageData 
{
   [EditorDescriptor(EditorDescriptorType = typeof(CollectionEditorDescriptor))]
   public virtual IList PersonList { get; set; }
}

public class Person
{    
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }
}

[PropertyDefinitionTypePlugIn]
public class PersonListProperty : PropertyList
{
    public PersonListProperty()
    {
        _objectSerializer = _objectSerializerFactory.Service.GetSerializer(KnownContentTypes.Json);
    }

    private Injected _objectSerializerFactory;

    private IObjectSerializer _objectSerializer;

    protected override Person ParseItem(string value)
    {
        return _objectSerializer.Deserialize(value);
    }
}

Свойство будет выглядеть так в режиме редактирования:

Чтобы перейти на новое свойство и использовать новый встроенный редактор, нам потребуется:

Определите новый тип PersonBlock и отметьте его как AvailableInEdit = false

[ContentType(AvailableInEditMode = false, GUID = "11157768-e09e-4da9-90df-54c73c61b270")] 
public class PersonBlock : BlockData
{    
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual int Age { get; set; }
    public virtual string Email { get; set; }
}

Чтобы использовать его на MyPage:

public class MyPage : PageData 
{
   public virtual IList PersonsNew { get; set; }
}

И новый опыт редактирования будет выглядеть так:

Обратите внимание, что больше нет необходимости определять свой собственный тип свойства.

Для перехода с IList в IList пользовательский фрагмент кода, который перебирает все экземпляры MyPage, анализирует то, что находится внутри свойства PersonList, а затем использует те же значения для создания списка экземпляров PersonBlock.

Грядут следующие улучшения

Мы планируем пойти еще дальше и позволить встраивать блоки в область содержимого, поэтому следите за обновлениями по этому вопросу.

В конце концов мы отключим команду «Быстрое редактирование» и будем продвигать новые встроенные блоки, которые больше не нуждаются в каких-либо хитростях, чтобы синхронизировать их жизненный цикл публикации с их родителем.

Нам также не понадобятся никакие команды типа «Опубликовать страницу с блоками».

Устаревание EPiServer.Labs.BlockEnhancements

Идея «встраивания» блоков в страницу возникла как часть нашей инициативы Labs, которая оказалась очень успешной.

Теперь, когда большая часть функций Лаборатории оказывается в официальном пакете, пришло время отказаться от нее.

28 марта 2023 г.

Read more:  FTC подала апелляцию. Битва за Activision Blizzard продолжается

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.