I have an Tridion.ContentManager.IdentifiableObject which may be a Page/Component etc and I wish to get the title of the publication it belongs to.
I am current able to get the publicationId like so:
IdentifiableObject.Id.PublicationId
but I wish to get the Publication title without doing a round trip to tridion. Is this possible?
It is possible. First of all cast your object to RepositoryLocalObject instead of IdentifiableObject and then you can do:
var item = (RepositoryLocalObject) subject;
item.OwningRepository.Title;
Related
I'd like to use the relationship filter to filter for a tags. This works fine when I pass a text string and it can search the EntityTitle, but I'd like to pass an entity_id to the filter.
I noticed in the details of the query results that the relationship filter has a "CompareAttribute=EntityTitle". Is there a way to edit that to make it EntityID?
Thanks.
At the moment filtering by a different property in related items could only be done in code. Heres' how
create your visual query as you would, with the only "mistake" being the wrong field
in your razor template, access the Query with var q = App.Query["queryname"];
then before you get the data, change the CompareAttribute. This will take a bit of fiddling about, because you have to cast the q from before to a IDataTarget and navigate up the query-tree like var relFilter = q.In["Default"].Source, then cast that again to the right type, and then change the relFilter.CompareAttribute = "Country";
...something like that :)
Afterwards you can access the query results with a foreach(var x in AsDynamic(q["Default"])) {...}
I've tried this where I wanted some locations grouped by region,
So I did:
region 1
address 1
address 2
region 2
address 3
address 4
So basically it should do the same except it would query by region.
So this is what I came up with:
#{
var someAddresses = App.Query["FilterAddresses"]["ListContent"];
someAddresses.Filter = region.RegionName;
Data.In.Add("someAddresses", someAddresses["Default"]);
}
#foreach (var pc in AsDynamic(someAddresses.List)) {
<li>#pc.Naam</li>
}
However it says:
CS1061: ToSic.Eav.DataSources.IDataStream does not contain a definition for Filter.
So should it be something else?
I'm writing a GUI extension and using the Anquilla framework to get a list of Keywords within a Category. I'm obtaining an XML document for the list of keywords then working with that document within my extension.
My problem is that the returned XML doesn't contain the Keyword's 'Description' value. I have the Title and Key etc.
My original code looks like this:
var category = $models.getItem("CATEGORYTCMID:);
var list = category.getListKeywords();
list.getXml();
A typical node returned is this:
<tcm:Item ID="tcm:4-1749-1024"
Type="1024" Title="rate_one" Lock="0" IsRoot="true"
Modified="2012-12-17T23:01:59" FromPub="010 Schema"
Key="rate_one_value" IsAbstract="false"
CategoryTitle="TagSelector"
CategoryID="tcm:4-469-512" Icon="T1024L0P0"
Allow="268560384" Deny="96" IsNew="false"
Managed="1024"/></tcm:ListKeywords>
So I've tried using a Filter to give me additional column information:
var filter = new Tridion.ContentManager.ListFilter();
filter.columns = Tridion.Constants.ColumnFilter.EXTENDED;
var list = category.getListKeywords(filter);
Unfortunately this only gives the additional XML attributes:
IsShared="true" IsLocalized="false"
I'd really like the description value to be part of this XML without having to create a Keyword object from the XML. Is such a thing possible?
cough any ideas? cough
I'm afraid you'll have to load the Keyword itself to get the Description.
It's not used in any lists, so it's not returned in the XML.
You could always create a List Extender to add this information to the list, but try to be smart about it since this extender will execute everytime a GetList is called.
Won't save you from having to open every keyword in the list, but you'll be doing it server-side (with Core Service/NetTcp for instance) which will probably be easier and faster than opening each keyword with Anguilla.
In this instance I only need the one keyword, so I simply get it from the CMS. Getting an object in Anguilla is a bit weird, here's the code:
In your main code area:
var selectedKy = $models.getItem("TcmUriOfKeywordHere");
if (selectedKy.isLoaded()) {
p.selectedKy = selectedKy;
this.onselectedKyLoaded();
} else {
$evt.addEventHandler(selectedKy, "load", this.onselectedKyLoaded);
selectedKy.load();
}
It's worth noting how I store the keyword in the properties of the item, so I can obtain it in the onselectedKyLoaded function
The function called once the item is loaded
ContentBloom.ExampleGuiExtension.prototype.onselectedKyLoaded = function (event) {
var p = this.properties;
var selectedDescription = p.selectedKy.getDescription();
// do what you need to do with the description :)
};
I resolved this, thanks to the answer here: https://stackoverflow.com/a/12805939/1221032 - Cheers Nuno :)
I am putting together a functional design for a site which will aims use the Tridion 2012 UI/XM to manage pages. There are 2 regions on the page, a main content area on the left and a side-bar on the right. Ideally users should be able to drag and drop content into and within these regions. In an ideal world I would like to define the regions along the lines of
Side Bar: any CP for which the CT has the text 'Right' in it.
Main: all other CPs
Looking at the documentation it seems that you need to explicitly use CT/Schema ID pairs to define regions. Is there any possibility to do this in any other way?
At the very least I would like to be able to define that the side bar allows a certain fixed set of CT/Schema ID pairs, but have the main region as a catchall bucket.. Is this possible?
It is also possible that the Side Bar is split into 2 regions, above and below an advertisement. Both regions should allow the same types of CP - as far as I understand this is not possible - is this correct? Are there any ideas for workarounds?
To configure regions that take all Content Types, You need to get Publication AppData and loop through the content types and build your json markup for enabling this.You could write C# TBB which includes on each page template and does this logic, you can define some metadata at CT level which determines which region it will go in and build the Region JSON markup.
Below is the snippet to get all Component types to add in one region. You could change the logic to get only right just by checking the template name.
// get the publication from the engine -- using TemplateBase Util..
Publication thisPub = GetPublication();
XmlElement seAppdata = thisPub.LoadApplicationData("SiteEdit").GetAs<XmlElement>();
XmlNamespaceManager seNsMgr = new XmlNamespaceManager(new NameTable());
seNsMgr.AddNamespace("se", "http://www.sdltridion.com/2011/SiteEdit");
seNsMgr.AddNamespace("xlink", "http://www.w3.org/1999/xlink");
XmlNodeList contentTypes = (XmlNodeList)seAppdata.SelectNodes("//se:ContentTypes/se:ContentType", seNsMgr);
List<String> contentTypeJson = new List<String>();
foreach (XmlNode contentType in contentTypes)
{
string templateId = contentType.SelectSingleNode("se:ComponentTemplate/#xlink:href", seNsMgr).Value;
string componentId = contentType.SelectSingleNode("se:Component/#xlink:href", seNsMgr).Value;
Component thisSchema = (Component)engine.GetObject(componentId);
string schemaId = thisSchema.Schema.Id;
// Add json formated string for Content Types
contentTypeJson.Add(string.Format("{{schema: \"{0}\", template: \"{1}\"}}", schemaId, templateId));
}
// Final Markup - JSON
String allRegionSeText = string.Format("<!-- Start Region: {{title: \"All Region\", allowedComponentTypes: [{0}], minOccurs: 1, maxOccurs: 5 }} -->", string.Join(",", contentTypeJson.ToArray()));
// Push to the package to use in DWT..
package.PushItem("ALL_REGION", package.CreateStringItem(ContentType.Text, allRegionSeText));
Hope this helps.
Have you tried creating a region without specifying CT/Schema pairs? I remember seeing in an early implementation that you could drop a content type anywhere because regions hadn't been configured properly (or perhaps at all).
I'll explain my problem as brief as possible. I have a variable bandName, the value is String that i get through an API.
public function haalNaam(selectedChart:Object):String
{
var bandName:String = selectedChart.name;
}
I use this var in a repeater for a label. This repeater repeats 5 times, so it shows the 5 most hyped artists:
<repeater>
<label text="{haalNaam(lastfmCollection.currentItem)}"/>
</repeater>
Next, i had to transport the var bandName to another component. I managed to do this with this command:
var theName = "LastFmApi(this.parentApplication).bandName".
This code works, but I only manage to get the bandName of the last element in the repeater (5th one). I have no idea how i can
receive the names of the artists 1,2,3 or 4. How can i get to those values?
First, it doesn't look like what you've pasted in is functional code (your haalName function doesn't return anything, and your repeater doesn't have the id referred to in the label).
Second, why don't you just use lastfmCollection.currentItem.name in the label's text property, and skip the function call?
Third, you don't say exactly what the goal is, so I'll assume that you want to click one of the items in the repeater and put the label text in the variable theName. That would look like this:
theName=(event.target as Label).text;
Note that you may also want to consider using a DataGroup.
Hey all, I was able to do this via a SELECT CASE statement, however I'm always trying to improve my code writing and was wondering if there was a better approach. Here's the scenario:
Each document has x custom fields on it.
There's y number of documents
However there's only 21 distinct custom fields, but they can obviously have n different combinations of them depending on the form.
So here's what I did, I created an object called CustomFields like so:
Private Class CustomFields
Public agentaddress As String
Public agentattorney As String
Public agentcity As String
Public agentname As String
Public agentnumber As String
Public agentstate As String
Public agentzip As String
... more fields here ....
End Class`
Then I went ahead and assigned the values I get from the user to each of those fields like so:
Set All of Our Custom Fields Accordingly
Dim pcc As New CustomFields()
pcc.agentaddress = agent.address1
pcc.agentattorney = cplinfo.attorneyname
pcc.agentcity = agent.city
pcc.agentname = agent.agencyName
pcc.agentnumber = agent.agentNumber
pcc.agentstate = agent.state
pcc.agentzip = agent.zip ....other values set to fields etc.
Now the idea is based upon what combo of fields come back based upon the document, we need to assign the value which matches up with that custom field's value. So if the form only needed agentaddress and agentcity:
'Now Let's Loop Through the Custom Fields for This Document
For Each cf As vCustomField In cc
Dim customs As New tblCustomValue()
Select Case cf.fieldname
Case "agentaddress"
customs.customfieldid = cf.customfieldid
customs.icsid = cpl.icsID
customs.value = pcc.additionalinfo
Case "agentcity"
customs.customfieldid = cf.customfieldid
customs.icsid = cpl.icsID
customs.value = pcc.additionalinfo
End Select
_db.tblCustomValues.InsertOnSubmit(customs)
_db.SubmitChanges()
This works, however we may end up having 100's of fields in the future so there a way to somehow "EVAL" (yes I know that doesn't exist in vb.net) the cf.fieldname and find it's corresponding value in the CustomFields object?
Just trying to write more efficient code and looking for some brainstorming here. Hopefully my code and description makes sense. If it doesn't let me know and I'll go hit my head up against the wall and try writing it again.
If I am reading your question correctly, you are trying to avoid setting the value of fields, when the field isn't used. If so, I would recommend you just go ahead and set the field to nothing in that case.