确保我的扩展列表始终显示"当前"数据?

Nun*_*res 8 tridion

当您为CME列表创建数据扩展器时 - 例如,为此示例添加Schema的列- 只要您执行强制List重新加载的操作,它就可以正常工作.

但是,某些操作不会强制列表重新加载(例如编辑文件夹中的组件,然后保存和关闭),看起来Anguilla正在加载使用不同机制加载的项目的数据,该机制仅加载数据有问题的项目(这是有道理的).

如果我希望我的扩展列表视图行为正常,并且每当给定项目更改时(而不是仅在重新加载列表视图时)还加载我的附加属性,我还需要做什么?

小智 13

我发现安圭拉如何处理这个问题.当您实现数据扩展器时,您正在扩展有关列表中显示的项目的信息,这基本上意味着您正在扩展相关项目后面的数据(模型).

Tridion中的每个Item在Anguilla Framework中都有自己的类,例如Component有自己的Tridion.ContentManager.Component javascript"class".

说到这一点,并回到显示组件的模式名称的示例,我们实际上并没有扩展模型,因为该信息已在组件中可用.但是,我们需要覆盖每个用于在项目所在列表中显示信息的方法,在本例中为Component.

因此,当我们处理Data Extender时,如果我们想要完全实现此功能,我们不仅需要定义数据扩展器:

<ext:dataextender 
    name="IntelligentDataExtender" 
    type="Com.Tridion.PS.Extensions.IntelligentDataExtender,PS.GUI.Extensions">
    <ext:description>Shows extra info</ext:description>
</ext:dataextender>
Run Code Online (Sandbox Code Playgroud)

但是我们还需要定义我们添加的列:

<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>
Run Code Online (Sandbox Code Playgroud)

一旦我们有了这个,GUI将显示我们刚刚添加的列:"附加信息"

那么,现在我们需要在编辑/签出项目等时实现列表刷新...

为此,我们需要扩展模型并在我们扩展的Object中实现一些方法.在这个例子中,我正在扩展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>
Run Code Online (Sandbox Code Playgroud)

<ext:modelextensions>
  <cfg:itemtypes>
    <cfg:itemtype id="tcm:64" implementation="Com.Tridion.PS.Extensions.UI.PSPage" />        
  </cfg:itemtypes>
</ext:modelextensions>
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我通过使用Javascript文件"/Scripts/PSPage.js"中定义的"Com.Tridion.PS.Extensions.UI.PSPage"类来扩展页面.

处理行刷新的唯一方法如下:

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])
};
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我正在实现"ExtendedInfo"属性,该属性是我的附加列中显示的属性.

在处理向列表添加列时,不仅仅是添加Data Extender.我将在我的博客中写一篇文章,提供一个完整的例子.

我希望这是有道理的.


Bor*_*nko 6

好吧,Jaime正确描述了CME如何更新列表中的项目.但我想添加一些关于List控件,域模型List和Items如何相互交互的附加信息.这可能有助于您构建具有类似功能的扩展.

大多数域模型List项都继承自Tridion.ContentManager.ListTcmItems类.在加载任何基于提到的类的List项时,它将在Lists Registry中注册(并在卸载List时未注册).这将允许Model使用已注册的列表作为Items的静态数据源,并更新这些列表中更改的Items数据.

更新项目静态数据

例如,我们已加载ListCategories,列表中只有一个类别:

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

// After list is loaded
list.getXml();
Run Code Online (Sandbox Code Playgroud)

getXml()返回类似的XML(简化):

<tcm:ListCategories>
    <tcm:Item ID="tcm:1-4-512" Type="512" Title="Keys" />
</tcm:ListCategories>
Run Code Online (Sandbox Code Playgroud)

之后,如果您尝试获取类别"密钥"的某些静态数据,它将已设置:

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

这是可能的,因为$models.getItem调用将做两件事:它将返回一个现有的(或创建一个新的)域模型对象,并$models.updateItemData使用它调用方法.此方法调用将遍历列表注册表中的所有已注册列表以及TimeStamp大于Item的Last Update TimeStamp将list.updateItemData使用模型对象调用的所有列表.

updateItemData方法将检查传递的Item是否在列表中,如果是,则将使用List中可用的静态数据更新Item.

更新列表中已更改项目的数据

当域模型Item被修改(更新,删除,创建新)时,会调用以下方法之一:

  • $models.itemUpdated
  • $models.itemRemoved

这些方法将通过列表注册表中的列表并调用list.itemUpdated(或list.itemRemoved).这些方法将检查是否传递Item包含在它们的List中,如果是,它们将从Item数据更新List xml.

为此目的getListItemXmlNode,Tridion.ContentManager.Item课堂上有一种方法.此方法将基于getListItemXmlAttributesItem上的方法提供的属性数组构建List xml节点.这就是Jaime在他的回答中提到的.

如果List xml已更新,则将在List对象上触发其中一个事件:

  • itemadd
  • itemupdate
  • itemremove

List在视图中的对象上收听这些事件将允许您及时更新列表控件.

因此,如果您希望此机制适用于您的扩展,请坚持以下规则:

  • 如果要创建新的域模型的列表对象-它应该继承Tridion.ContentManager.ListTcmItems类或者它应该实现getId(),itemUpdated(item),itemsUpdated(item),itemRemoved(item)updateItemData(item)方法
  • 如果要查看List控件中的更改 - 将处理程序附加到域模型List对象上的相应事件并更新List控件
  • 如果要创建新的域模型Item - 它应该继承Tridion.ContentManager.Item类,您应该改进getListItemXmlAttributes方法以返回List的正确属性数组