Javascript

List view getListItemXmlAttributes method fails with child publication items

25 September 2026 · 12 min read

List view getListItemXmlAttributes method fails with child publication items

Working with Tridion’s Content Delivery API can be incredibly powerful, enabling dynamic content presentation tailored to specific needs. However, developers sometimes encounter unexpected hurdles. One common issue arises when using the getListItemXmlAttributes method in List views, particularly when dealing with child publication items. This can lead to frustrating errors and roadblocks in your development process. This post delves into the nuances of this problem, exploring its root causes and providing practical solutions to help you navigate this tricky terrain and build robust, reliable Tridion implementations.

Understanding the getListItemXmlAttributes Method

The getListItemXmlAttributes method is essential for retrieving metadata associated with items in a List view. This metadata can be crucial for customizing the display and behavior of list items. However, when child publication items are involved, the method can sometimes fail to retrieve the expected attributes, throwing errors or returning null values.

This issue often stems from how Tridion handles inheritance and component linking in the context of List views. Child publications may inherit components from parent publications, and the relationships between these components can impact the behavior of getListItemXmlAttributes. Understanding these relationships is key to resolving the issue.

A common scenario involves using a Dynamic Component Presentation (DCP) within a List view. If the DCP relies on specific component metadata, and that metadata isn’t properly resolved for child publication items, the getListItemXmlAttributes method might fail. This can manifest in various ways, from exceptions to simply not displaying the desired information.

Common Causes of the Issue

Several factors contribute to the failure of getListItemXmlAttributes with child publication items. One frequent culprit is incorrect component linking. If the links between components in parent and child publications are not properly configured, the method may not be able to access the necessary metadata.

Another common cause is template mismatches. If the templates used in the parent and child publications are inconsistent or have conflicting metadata definitions, this can also lead to problems with getListItemXmlAttributes.

Furthermore, caching issues can sometimes exacerbate the problem. Outdated cached data can lead to inconsistencies and unexpected behavior. Clearing the cache can often resolve these issues, but it’s essential to identify and address the underlying cause.

Troubleshooting and Solutions

When faced with this issue, there are several troubleshooting steps you can take. First, verify the component linking between the parent and child publications. Ensure that the components are correctly linked and that the necessary metadata is available in the child publication.

  1. Check Component Linking: Validate that components are correctly linked between parent and child publications. 3. Review Templates: Ensure consistency between templates used in parent and child publications, especially regarding metadata definitions. 5. Clear Caches: Clear the Tridion cache to eliminate potential issues with outdated data. Sometimes a full application pool recycle is necessary. Next, examine the templates used in both publications. Look for any inconsistencies or conflicts in metadata definitions. Ensure that the templates are designed to handle child publication items correctly.

Clearing the Tridion cache can also be helpful. Outdated cached data can sometimes cause unexpected behavior. Clearing the cache can force Tridion to retrieve fresh data and resolve any inconsistencies.

Here are some key considerations for preventing this issue:

  • Consistent Template Design: Use a consistent approach to metadata definitions across all templates.
  • Thorough Testing: Test your implementation thoroughly in both parent and child publications to catch potential issues early.

Best Practices for Working with List Views and Child Publications

To avoid encountering this issue in the first place, follow these best practices:

  • Establish a clear and consistent metadata schema across your publications.
  • Thoroughly test your List view implementations in both parent and child publications.
  • Implement robust error handling to gracefully manage any unexpected issues.

By adhering to these practices, you can minimize the risk of encountering problems with getListItemXmlAttributes and ensure the smooth operation of your Tridion implementation. A well-defined content model and rigorous testing are crucial for success.

Consider leveraging the power of the Tridion community for additional support and resources. Sharing your experiences and solutions can benefit other developers facing similar challenges.

Working with Inherited Content

When dealing with inherited content, pay close attention to how metadata is inherited and how it interacts with your List views. Ensure that your templates are designed to handle inherited metadata correctly and that your List views are configured to retrieve the appropriate attributes. This will help prevent unexpected behavior and ensure the accurate display of information.

Remember that clear documentation is paramount. Documenting your implementation, including how you handle metadata inheritance and List views, can save you time and effort in the long run. This documentation can be invaluable for troubleshooting and future development.

For deeper insights into Tridion development, refer to the official SDL documentation and community forums. These resources provide valuable information and best practices for working with Tridion and can help you overcome various challenges.

External Resources:

[Infographic Placeholder: Illustrating the relationship between parent and child publications and how metadata is inherited.]

Frequently Asked Questions

Q: How can I determine if the issue is related to caching?

A: Try clearing the Tridion cache and restarting the application pool. If the issue resolves, it was likely cache-related. However, this is a temporary fix; investigate the underlying cause to prevent recurrence.

Successfully working with Tridion’s getListItemXmlAttributes method in the context of child publications requires a deep understanding of how Tridion handles inheritance and component linking. By carefully considering these factors and implementing the solutions and best practices outlined in this post, you can avoid common pitfalls and build robust and reliable Tridion implementations. Remember that proactive planning, thorough testing, and clear documentation are key to success. Exploring resources like the SDL documentation and engaging with the Tridion community can further enhance your expertise and help you navigate the complexities of Tridion development. Consider exploring related topics like template development, component linking strategies, and advanced caching techniques to further enhance your Tridion skills.

Question & Answer :
I have created a JS class to populate SG/Folder list view data, when items are modified. (As per Jaime’s approach) Everything works great when I operate on items in the publication they’re created in.

Ex: I open a component or page and the custom locked by column immediately updates and shows my user name.

However, when I go to a child publication and repeat that process, I get the window asking if I want to localize or edit the parent item. If I select to edit the parent window, the code doesn’t work. I haven’t quite figured it out yet with initial debugging. Chrome seems to swallow the error, Firefox gives me a cryptic:

Timestamp: 6/22/2012 3:42:54 PM

Error: uncaught exception: [Exception… “Component returned failure code: 0x80004002 (NS_NOINTERFACE) [nsIWebProgress.DOMWindow]” nsresult: “0x80004002 (NS_NOINTERFACE)” location: “JS frame :: chrome://browser/content/tabbrowser.xml :: :: line 545” data: no]

Does anyone have any initial ideas? I’ll try to post some code later on…

Code from PageEx.js:

Type.registerNamespace("MyCompany.Tridion.RTFExtensions"); /* * Constructor */ MyCompany.Tridion.RTFExtensions.PageEx = function (id) { Type.enableInterface(this, "MyCompany.Tridion.RTFExtensions.PageEx"); this.addInterface("Tridion.ContentManager.Page", [id]); var p = this.properties; p.versionNumberString = undefined; p.modifiedBy = undefined; p.lockedBy = undefined; p.approvalStatus = undefined; p.publishDate = undefined; p.previousVersion = undefined; p.previousApprovalStatus = undefined; p.customModifiedDate = undefined; p.initialModifierUserName = undefined; }; /* * sends the list xml string for the item */ MyCompany.Tridion.RTFExtensions.PageEx.prototype.getListItemXmlAttributes = function (customAttributes) { var attribs = {}; $extUtils.getListItemXmlAttributes(customAttributes,this, attribs); return this.callBase("Tridion.ContentManager.Page", "getListItemXmlAttributes", [attribs]); }; /* * This method gets called when an item is opened from list view. node parameter has the information * displayed in the list view as attributes. We are getting cutom data extender column information * from this xml node and storing it in this class member for returning it from getListItemXmlAttributes method */ MyCompany.Tridion.RTFExtensions.PageEx.prototype.setDataFromList = function (node, parentId, timeStamp) { $extUtils.setDataFromList(node,parentId,timeStamp,this); this.callBase("Tridion.ContentManager.Page", "setDataFromList", [node, parentId, timeStamp]); }; /* * Gets item icon */ MyCompany.Tridion.RTFExtensions.PageEx.prototype.getItemIcon = function () { var icon = this.callBase(this.defaultBase, "getItemIcon"); return icon; }; 

Code from utils.js:

// reloads the list view for the given id (used in list view data refresh when JS cant get the required data without reloading) MyCompany.Tridion.RTFExtensions.Utilities.reloadListView = function (listTcmId) { var registry = $models.getListsRegistry(); for(var key in registry) { var entry = $models.getItem(registry[key]); if (entry && entry.getParentId() == listTcmId) { entry.unload(); return true; } } return false; } /* * This method gets called when an item is opened from list view. node parameter has the information * displayed in the list view as attributes. We are getting cutom data extender column information * from this xml node and storing it in this class member for returning it from getListItemXmlAttributes method */ MyCompany.Tridion.RTFExtensions.Utilities.setDataFromList = function (node, parentId, timeStamp, itemClicked) { var p = itemClicked.properties; if (!timeStamp || timeStamp > itemClicked.getTimeStamp()) { var tmp; if (tmp = node.getAttribute('Version')) { p.versionNumberString = tmp; p.previousVersion = tmp; } if (tmp = node.getAttribute('ModifiedBy')) { p.modifiedBy = tmp; p.initialModifierUserName = tmp; } if (tmp = node.getAttribute('LockedBy')) { p.lockedBy = tmp; } if (tmp = node.getAttribute('ApprovalStatus')) { p.approvalStatus = tmp; p.previousApprovalStatus = tmp; } if (tmp = node.getAttribute('PublishDate')) { p.publishDate = tmp; } if (p.customModifiedDate === undefined) { if (tmp = node.getAttribute('Modified')) { p.customModifiedDate = tmp; } } } } /* * sends the list xml string for the item in the list view. */ MyCompany.Tridion.RTFExtensions.Utilities.getListItemXmlAttributes = function (customAttributes, listViewObject,attribs) { var p = listViewObject.properties; $extUtils.getListViewItemLockedByName(p,listViewObject); if (customAttributes) { for (var attr in customAttributes) { attribs[attr] = customAttributes[attr]; } } attribs["Version"] = $extUtils.getListViewItemUpdatedVersion(p,listViewObject); //modified name has to come after the version update... $extUtils.getListViewItemModifiedByName(p,listViewObject); attribs["ApprovalStatus"] = $extUtils.getListViewItemApprovalStatus(p,listViewObject); attribs["PublishDate"] = $extUtils.getListViewItemPublishDate(p,listViewObject); //set default values if (p.versionNumberString != undefined) { var iResult = p.versionNumberString.localeCompare(p.previousVersion); if (p.previousVersion === undefined || iResult > 0) { //it's been updated! p.previousVersion = p.versionNumberString; p.previousApprovalStatus = p.approvalStatus; //also need to update modified date p.customModifiedDate = $extUtils.getListViewItemUpdatedModifiedDate(p,listViewObject); p.initialModifierUserName = p.modifiedBy; } } attribs["Modified"] = p.customModifiedDate; attribs["LockedBy"] = p.lockedBy; attribs["ModifiedBy"] = p.modifiedBy; }; /* * This method sets the property of the Revisor owner on the item in the list view. however, if it's not the current user * we have no way to look that up in JS so we have to reload the list view. */ MyCompany.Tridion.RTFExtensions.Utilities.getListViewItemModifiedByName = function (p,listViewObject) { var p = listViewObject.properties; var xmlDoc = listViewObject.getXmlDocument(); if (xmlDoc) { //modifier should always exist... var modifierId = $xml.getInnerText(xmlDoc, "/tcm:*/tcm:Info/tcm:VersionInfo/tcm:Revisor/@xlink:title"); if (modifierId != undefined) { var u = Tridion.UI.UserSettings.getJsonUserSettings(true); if (modifierId == u.User.Data.Name) { var strDescription = u.User.Data.Description.split('('); p.modifiedBy = strDescription[0]; return; } else { //we're in trouble... //let's hope it's the initial modifier we had... if (p.previousVersion == p.versionNumberString) { //whew... p.modifiedBy = p.initialModifierUserName; return; } if (!$extUtils.reloadListView(listViewObject.getOrganizationalItemId())) { //hrm. something failed on the reload? not sure what else to do: p.modifiedBy = modifierId; } } } else { //shouldn't ever happen. p.modifiedBy = ""; return; } } }; /* * This method sets the property of the lock owner on the item in the list view. however, if it's not the current user * we have no way to look that up in JS so we have to reload the list view. */ MyCompany.Tridion.RTFExtensions.Utilities.getListViewItemLockedByName = function (p,listViewObject) { var xmlDoc = listViewObject.getXmlDocument(); if (xmlDoc) { //this will be user id. no sense getting tcmid... can't look it up without async call var lockedUserId = $xml.getInnerText(xmlDoc, "/tcm:*/tcm:Info/tcm:VersionInfo/tcm:ItemLock/tcm:User/@xlink:title"); if (lockedUserId != undefined) { //see if it's the current user. most likely... var u = Tridion.UI.UserSettings.getJsonUserSettings(true); if (lockedUserId == u.User.Data.Name) { var strDescription = u.User.Data.Description.split('('); p.lockedBy = strDescription[0]; return; } //it's not the current user. no synch way to do what we want, plus the JS call doesn't get the workflow version anyway. refresh the parent view if (!$extUtils.reloadListView(listViewObject.getOrganizationalItemId())) { //hrm. something failed on the reload? not sure what else to do: p.lockedBy = lockedUserId; } } else { //clear it out since there's no lock owner p.lockedBy = ""; } } }; /* * Gets the ApprovalStatus from the item * This makes absolutely no sense... but for some reason the approval status gets wiped out when this method * enters. so I had to use a "previous approval status" variable to maintain it. no idea why. I don't see anything * else that should be touching it... but clearly something clears it out. */ MyCompany.Tridion.RTFExtensions.Utilities.getListViewItemApprovalStatus = function (p,listViewObject) { //check if the item has actually been modified. if (p.versionNumberString != p.previousVersion) { var xmlDoc = listViewObject.getXmlDocument(); if (xmlDoc) { p.approvalStatus = $xml.getInnerText(xmlDoc, "/tcm:*/tcm:Info/tcm:Data/tcm:ApprovalStatus/@xlink:title"); } } else { p.approvalStatus = p.previousApprovalStatus; } if (p.approvalStatus === undefined || p.approvalStatus.toUpperCase() == 'UNAPPROVED') { var foo = p.approvalStatus; p.approvalStatus = 'WIP'; } return p.approvalStatus; }; /* * Gets the PublishDate from the item list view */ MyCompany.Tridion.RTFExtensions.Utilities.getListViewItemPublishDate = function (p,listViewObject) { //modification won't alter publish date. var p = listViewObject.properties; return p.publishDate; }; /* * get the modified date for the workflow version, overwrite OOB since that uses last major version */ MyCompany.Tridion.RTFExtensions.Utilities.getListViewItemUpdatedModifiedDate = function (p,listViewObject) { var xmlDoc = listViewObject.getXmlDocument(); var modDate = $xml.getInnerText(xmlDoc, "/tcm:*/tcm:Info/tcm:VersionInfo/tcm:RevisionDate"); return modDate; } /* * Gets the updated Version information from the item */ MyCompany.Tridion.RTFExtensions.Utilities.getListViewItemUpdatedVersion = function (p,listViewObject) { var p = listViewObject.properties; var xmlDoc = listViewObject.getXmlDocument(); var newVersionString = undefined; if (xmlDoc) { newVersionString = String.format("{0}.{1}", $xml.getInnerText(xmlDoc, "/tcm:*/tcm:Info/tcm:VersionInfo/tcm:Version"), $xml.getInnerText(xmlDoc, "/tcm:*/tcm:Info/tcm:VersionInfo/tcm:Revision")); } if (newVersionString != undefined) { //want to ensure we're getting a LATER version than we had (because it will try to load the non-workflow version afterwards... var iResult = newVersionString.localeCompare(p.previousVersion); if (p.previousVersion === undefined || iResult > 0) { p.versionNumberString = newVersionString; } else { p.versionNumberString = p.previousVersion; } } else { p.versionNumberString = p.previousVersion; } return p.versionNumberString; }; function launchPopup(winURL, winName, winFeatures, winObj) { // this will hold our opened window var theWin; // first check to see if the window already exists if (winObj != null) { // the window has already been created, but did the user close it? // if so, then reopen it. Otherwise make it the active window. if (!winObj.closed) { winObj.focus(); return winObj; } // otherwise fall through to the code below to re-open the window } // if we get here, then the window hasn't been created yet, or it // was closed by the user. theWin = window.open(winURL, winName, winFeatures); return theWin; } var $extUtils = MyCompany.Tridion.RTFExtensions.Utilities; 

[Exception… “Component returned failure code: 0x80004002 (NS_NOINTERFACE) [nsIWebProgress.DOMWindow]”

This means that there was no window assigned to the nsIWebProgress object. So it has nowhere to display data.

nsresult: “0x80004002 (NS_NOINTERFACE)” location: “JS frame :: chrome://browser/content/tabbrowser.xml :: :: line 545” data: no]

This is telling you what file is associated with that error. and what line it faulted on.

But the real key is the NS_NOINTERFACE error. Which means the interface has not been registered.

You are using Type.enableInterface(). Is that a custom method you are declaring somewhere else ? I don’t see it. You might want to change that to .registerInterface()

See this link Type Class and Type.registerInterface()