Make sure my extended lists always show "current" data?

When you create a Data Extender for a CME list β€” for example, to add a column for a schema, as in this example β€” everything works fine and dandy when you follow the steps that force the list to reload.

However, some actions do not reload the list (for example, editing a component in a folder and then saving and closing), and it seems that Anguilla is loading data for an item that has been modified using another mechanism that only loads data for the item in question (which has the meaning).

If I wanted my extended list view to work correctly, and also load my additional attributes whenever this item changes (and not just after the list is reloaded), what else do I need to do?

+8
tridion
source share
4 answers

I found how Anguilla takes care of this. When you implement the Data Extender, you expand the information about the elements displayed in the list, which basically means that you expand the data (model) behind the element in question.

Each element in Tridion has its own class in the Anguilla platform, for example, the component has its own javascript class Tridion.ContentManager.Component.

Having said that, and return to the example that shows the name of the component schema, we do not actually extend the model, since this information is already available in the component. However, we need to rewrite the methods that are open to each information used to display the lists in which the item is located, in this case the Component.

So, when we are dealing with Data Extender, if we want to fully implement this functionality, we need not only to define a data extender:

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

But also we need to determine which column we are adding:

 <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> 

After that, the GUI will display the newly added column: "Additional Information"

Well, now we need to get the list updated when the item is edited / checked out and turned on, etc.

To do this, we need to expand the model and implement several methods in the object that we are expanding. In this example, I am expanding the Page object, so whenever a page is edited, the line in the list that we want to update is updated along with the rest of the cells in the table.

To extend the model, we need to determine what types we extend, in this example I am going to use the "Page" class as an example. First of all, you need to define the model extension in the configuration file of your editor:

 <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> 

and

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

As you can see, I am expanding the page using the class "Com.Tridion.PS.Extensions.UI.PSPage", which is defined in the Javascript file "/Scripts/PSPage.js".

The only method that handles updating the string is the following:

 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]) }; 

As you can see, I am implementing the β€œExtendedInfo” attribute, which is displayed in my extra column.

There's more than just adding a Data Extender when working with adding a column to our lists. I will write a post on my blog here to provide a fully working example.

Hope this makes sense.

+13
source share

Well, Jaime correctly described how CME updates items in lists. But I want to add more information about how the List controls, the list of models, and the domain elements interact with each other. This can help you create your own extension with similar functionality.

Most elements of the domain model list are inherited from the Tridion.ContentManager.ListTcmItems class. At the moment when any element of the list based on the specified class is loaded, it will be registered in the List Registry (and not registered when the List is unloaded). This will allow the model to use registered lists as a source of static data for items and to update changed item data in these lists.

Update static item data

For example, we loaded ListCategories and there is only one category in the list:

 var pub = $models.getItem("tcm:0-1-1"); var list = pub.getListCategories(); list.load(); // After list is loaded list.getXml(); 

That getXml() returns XML as (simplified):

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

After that, if you try to get some static data for the "Keys" category, it will already be installed:

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

This is possible because calling $models.getItem will do two things: it will return an existing (or create a new) domain model object and call the $models.updateItemData method with it. This method call will go through all registered lists in the list registry and for all lists whose TimeStamp is greater than the Last Update element, TimeStamp will call list.updateItemData with the model object.

The updateItemData method checks if the passed item is in the list, and if it is, the item will be updated with static data available from the List.

Updating the data of the changed items in the list

When the domain model element is changed (updated, deleted, created new), one of these methods is called:

  • $models.itemUpdated
  • $models.itemRemoved

These methods will go through the list in the list of lists and call list.itemUpdated (or list.itemRemoved ). These methods will be tested. The element is contained in their list, and if they will update the xml list from the element data.

For this purpose, there is a getListItemXmlNode class in the Tridion.ContentManager.Item class. This method will build the List xml node based on the array of attributes provided by the getListItemXmlAttributes method for the element. This is what Jaime mentioned in his answer.

If the xml list has been updated, one of these events will be fired in the List object:

  • itemadd
  • itemupdate
  • itemremove

Listening to these events in the List object in your view will allow you to update your list control in a timely manner.

So, if you want this mechanism to work with your extension, stick to the following rules:

  • If you create a new object for a list of domain objects, it must inherit the Tridion.ContentManager.ListTcmItems class or it must implement the getId() , itemUpdated(item) , itemsUpdated(item) , itemRemoved(item) and updateItemData(item)
  • If you want to see changes in the List control, attach the handlers to the corresponding events in the list object of the domain model and update the List control
  • If you create a new domain model object, it must inherit the Tridion.ContentManager.Item class, and you must improve the getListItemXmlAttributes method to return the correct array of attributes for the list
+6
source share

The CME will indeed update the items in the list dynamically after saving, without going to the server.

To do this, it calls a method called "getListItemXml", which returns an XML update element for the list. Then it will update or add this item, which will update or add the item as a list.

getListItemXml is a method of various model objects.

So how do you use this? I'm not sure.

Perhaps you could overwrite the method (or maybe getListItemXmlAttributes best) with your own to add extra data?

The itemupdate event is fired every time an item is updated in the list. You can connect to this by doing something like this:

 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); 

I suppose you could use this to update the list entry for an item after the fact. Be sure to call removeEventHandler at some point.

None of this is optimal, obviously. But I don’t know of any extension point that would solve this particular problem.

+2
source share

I think that I (will try) to implement this by periodically monitoring the items in the folder and updating this list after this polling mechanism has detected a change in this folder.

For example, I would write some wait time or a javascript interval that runs in the background and checks for items in the current folder. If it detects a change, it starts updating the list.

In addition, you can also try to intercept an action that changed your list (for example, creating a new item), possibly using an event system, and as such update the list. I do not think this is very different from the first approach, since I think that it still implies some level of polling from the GUI.

0
source share

All Articles