Убедитесь, что в моих расширенных списках всегда отображаются "текущие" данные - PullRequest
8 голосов
/ 03 апреля 2012

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

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

Если бы я хотел, чтобы мой расширенный вид списка работал правильно, а также загружал мои дополнительные атрибуты при каждом изменении данного элемента (а не только при перезагрузке представления списка), что еще мне нужно сделать?

Ответы [ 4 ]

13 голосов
/ 05 апреля 2012

Я обнаружил, как Ангилья заботится об этом. При реализации расширителя данных вы расширяете информацию, касающуюся элементов, отображаемых в списке, что в основном означает, что вы расширяете данные (модель) за рассматриваемым элементом.

Каждый элемент в Tridion имеет свой собственный класс в Anguilla Framework, например, у компонента есть свой собственный класс «Tridion.ContentManager.Component» javascript.

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

Итак, когда мы имеем дело с Расширителем Данных, если мы хотим полностью реализовать эту функциональность, нам нужно не только определить расширитель данных:

<ext:dataextender 
    name="IntelligentDataExtender" 
    type="Com.Tridion.PS.Extensions.IntelligentDataExtender,PS.GUI.Extensions">
    <ext:description>Shows extra info</ext:description>
</ext:dataextender>

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

<ext:lists>
    <ext:add>
        <ext:extension name="IntelligentColumnExtender"   
                       assignid="IntelligentDataColumnExtender">
          <ext:listDefinition>
            <ext:selectornamespaces/>
            <ext:columns>
              <column 
                  xmlns="http://www.sdltridion.com/2009/GUI/extensions/List"
                  id="IntelligentData" 
                  type="data"  
                  title="Additional Info" 
                  selector="@ExtendedInfo" 
                  translate="String"/>
            </ext:columns>
          </ext:listDefinition>
          <ext:apply>
            <ext:view name="DashboardView" />
          </ext:apply>
        </ext:extension>
      </ext:add>
  </ext:lists>

Как только мы получим это, в графическом интерфейсе отобразится добавленный столбец: «Дополнительная информация»

Что ж, теперь нам нужно добиться обновления списка, когда элемент редактируется / извлекается и извлекается и т. Д. ...

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

Чтобы расширить модель, нам нужно определить, какие типы мы расширяем, в этом примере я собираюсь использовать класс «Page» в качестве примера. Прежде всего вам необходимо определить расширение модели в файле конфигурации вашего редактора:

<cfg:group name="Com.Tridion.PS.Extensions.UI.Model"
     merger="Tridion.Web.UI.Core.Configuration.Resources.DomainModelProcessor" 
     merge="always">
    <cfg:domainmodel name="Com.Tridion.PS.Extensions.UI.Model">
      <cfg:fileset>
        <cfg:file type="script">/Scripts/PSPage.js</cfg:file>            
      </cfg:fileset>
      <cfg:services />
    </cfg:domainmodel>
</cfg:group>

и

<ext:modelextensions>
  <cfg:itemtypes>
    <cfg:itemtype id="tcm:64" implementation="Com.Tridion.PS.Extensions.UI.PSPage" />        
  </cfg:itemtypes>
</ext:modelextensions>

Как вы можете видеть, я расширяю страницу с помощью класса "Com.Tridion.PS.Extensions.UI.PSPage", который определен в файле Javascript "/Scripts/PSPage.js".

Единственный метод, который обрабатывает обновление строки, это:

Com.Tridion.PS.Extensions.UI.PSPage.prototype.getListItemXmlAttributes 
= function PSPage$getListItemXmlAttributes(customAttributes) {
    var attribs = {};
    var p = this.properties;   

    if (customAttributes) {
        for (var attr in customAttributes) {
            attribs[attr] = customAttributes[attr];
        }
    }
    //This adds my custom column back when the item is updated
    attribs["ExtendedInfo"] = p.extendedInfo;

    return this.callBase(
        "Tridion.ContentManager.Page", 
        "getListItemXmlAttributes", 
        [attribs])
};

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

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

Надеюсь, это имеет смысл.

6 голосов
/ 11 апреля 2012

Хорошо, Хайме правильно описал, как обновления CME изменили элементы в списках. Но я хочу добавить дополнительную информацию о том, как элементы управления List, модель домена List и Items взаимодействуют друг с другом. Это может помочь вам создать собственное расширение с похожей функциональностью.

Большая часть модели домена Элементы списка наследуются от Tridion.ContentManager.ListTcmItems класса. В тот момент, когда какой-либо элемент Списка, основанный на указанном классе, загружен, он будет зарегистрирован в Реестре списков (и незарегистрирован при выгрузке Списка). Это позволит модели использовать зарегистрированные списки в качестве источника статических данных для элементов и обновлять измененные данные элементов в этих списках.

Обновить элемент статические данные

Например, мы загрузили ListCategories, и в списке есть только одна категория:

var pub = $models.getItem("tcm:0-1-1");
var list = pub.getListCategories();
list.load();

// After list is loaded
list.getXml();

То, что getXml() возвращает XML как (упрощенно):

<tcm:ListCategories>
    <tcm:Item ID="tcm:1-4-512" Type="512" Title="Keys" />
</tcm:ListCategories>

После этого, если вы попытаетесь получить статические данные для категории «Ключи», они будут уже установлены:

var category = $models.getItem("tcm:1-4-512");
category.isLoaded();         // return false
category.isStaticLoaded();   // return false
category.getTitle();         // return undefined
category.getStaticTitle();   // return "Keys"!

Это возможно, потому что вызов $models.getItem сделает две вещи: он вернет существующий (или создаст новый) объект модели домена и вызовет с ним метод $models.updateItemData. Этот вызов метода будет проходить через все зарегистрированные списки в реестре списков и для всех списков, у которых TimeStamp больше, чем у последнего обновления элемента TimeStamp, будет вызываться list.updateItemData с объектом модели.

Метод updateItemData проверит, есть ли переданный Предмет в списке, и если он есть, то Предмет будет обновлен статическими данными, которые доступны из Списка.

Обновление данных об измененных элементах в списке

Когда элемент модели домена изменяется (обновляется, удаляется, создается новый), вызывается один из этих методов:

  • $models.itemUpdated
  • $models.itemRemoved

Эти методы пройдут по спискам в реестре списков и вызовут list.itemUpdated (или list.itemRemoved). Эти методы будут проверять, передан ли Item, содержится в их Списке, и если это так, они обновят XML-список из данных Элемента.

Для этой цели в классе Tridion.ContentManager.Item существует метод getListItemXmlNode. Этот метод создаст узел List xml на основе массива атрибутов, предоставленного методом getListItemXmlAttributes для Item. Это то, что Хайме упоминал в своем ответе.

Если список XML был обновлен, одно из этих событий будет запущено для объекта списка:

  • itemadd
  • itemupdate
  • itemremove

Прослушивание этих событий на объекте List в вашем представлении позволит вам своевременно обновлять свой элемент управления списком.

Поэтому, если вы хотите, чтобы этот механизм работал с вашим расширением, придерживайтесь следующих правил:

  • Если вы создаете объект списка новой модели домена - он должен наследовать класс Tridion.ContentManager.ListTcmItems или реализовывать методы getId(), itemUpdated(item), itemsUpdated(item), itemRemoved(item) и updateItemData(item)
  • Если вы хотите увидеть изменения в элементе управления List - присоедините обработчики к соответствующим событиям в модели списка объекта домена и обновите свой элемент управления List *
  • Если вы создаете новую модель предметной области - она ​​должна наследовать класс Tridion.ContentManager.Item, и вы должны усовершенствовать метод getListItemXmlAttributes, чтобы возвращать правильный массив атрибутов для Списка
2 голосов
/ 04 апреля 2012

CME действительно обновит элементы в списке динамически после сохранения, не обращаясь к серверу.

Для этого он вызывает метод с именем "getListItemXml", который возвращает элемент XML обновления длясписок.Затем он обновит или добавит этот элемент, который обновит или добавит элемент в представлении списка.

getListItemXml - это метод различных объектов Model.

Итак, как вы можете воспользоваться этим?Я не уверен.

Возможно, вы могли бы перезаписать метод (или, возможно, getListItemXmlAttributes) своим собственным, чтобы добавить дополнительные данные?

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

var myEventHandler = function(event)
{
    $log.message("Item updated. TridionEvent object passed: " + event);
}

var view = $display.getView();
var list = view.getListObject("uri-of-Folder");
list.addEventListener("itemupdate", myEventHandler);

Я полагаю, вы можете использовать это для обновления записи в списке для элемента после факта.Обязательно вызовите removeEventHandler и в какой-то момент.

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

0 голосов
/ 03 апреля 2012

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

Например, я бы написал несколькоТайм-аут или интервал JavaScript, который работает в фоновом режиме и проверяет элементы в текущей папке.Если он обнаруживает изменение, он инициирует обновление списка.

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

...