2sxc Relationship Filter without EntityTitle - 2sxc

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?

Related

Datasource Paging Issue (Revised Again)

See Datasource Paging Issue (Revised)
for the original question.
Markus, you were kind enough to help with out with the issue of incorporating a record count into a query using a calculated datasource. I have a search form with 15 widgets - a mix of date ranges, dropdowns, text values and ._contains, ._equals, ._greaterThanOrEquals, ._lessThanOrEquals, etc.
I have tested this extensively against mySQL SQL code and it works fine.
I have now added a 16th parameter PropertyNames, which is a list with binding #datasource.query.filters.Property.PropertyName._in and Options blank. The widget on the form is hidden because it is only used for additional filtering.
Logic such as the following is used, such that a particular logged-in user can only view their own properties. So if they perform a search and the Property is not specified we do:-
if (params.param_Property === null && canViewAllRecords === false) {
console.log(params.param_PropertyNames); // correct output
ds.filters.Property.PropertyName._in = params.param_PropertyNames;
}
The record count (records.length) is correct, and if I for loop through the array of records the record set is correct.
However, on the results page the table displays a larger resultset which omits the PropertyNames filter. So if I was to search on Status 'Open' (mySQL results 50) and then I add a single value ['Property Name London SW45'] for params.param_PropertyNames the record count is 6, the records array is 6 but the datasource display is 50. So the datasource is not filtering on the property array.
Initially I tried without adding the additional parameter and form widget and just using code such as
if (params.param_Property === null && canViewAllRecords === false) {
console.log(params.param_PropertyNames); // correct output
ds.filters.Property.PropertyName._in = properties; // an array of
properties to filter out
}
But this didn't work, hence the idea of adding a form widget and an additional parameter to the calculated recordcount datasource.
If I inspect at query.parameters then I see:-
"param_Status": "Open",
"param_PropertyNames": ["Property Name London SW45"],
If I inspect query.filters:-
name=param_Status, value=Open
name=param_PropertyNames, value=[]}]}
It looks as though the filter isn't set. Even hard coding
ds.filters.Property.PropertyName._in = ['Property Name London SW45'],
I get the same reuslt.
Have you got any idea what would be causing this issue and what I can do for a workaround ?
Using a server side solution I would suggest editing both your SQL datasource query script (server side) that is supposed to filter by this property list and including the same code in your server side script for your calculated Count datasource. The code would look something like this, not knowing your exact details:
var subquery = app.models.Directory.newQuery();
subquery.filters.PrimaryEmail._equals = Session.getActiveUser().getEmail();
subquery.prefetch.Property._add();
var results = subquery.run();
if(!results[0].CanViewAllRecords) {
query.filters.Property.PropertyName._in = results[0].Property.map(function(i) {return i.PropertyName;});
}
By adding this code you are filtering your directory by your current user and prefetching the Property relation table, then you set the filter only if your user canviewallRecords is false and use JS map function to create an array of the PropertyName field in the Property table. As I stated, your code may not be exactly the same depending on how you have to retrieve your user canviewallrecords property and then of course I don't know your relation between user and Property table either, is it one-to-many or other. But this should give you an idea how to implement this on server side.

Umbraco: x.GetPropertyValue("myProp") vs x.myProp

I use Umbraco v4, but think this should be a common problem.
I have a generic property "myNode" of "Content Picker", that should obtain a DynamicNode...
so doying myObj.myNode I obtain the node itself... so can use myObj.myNode.Url
But doying the myObj.GetPropertyValue("myNode") I obtain the ... string ID value of the node... so can't anymore do myObj.GetPropertyValue("myNode").Url (string does not have Url property)
I can't use directly myObj.myNode, because the name is "dynamic" (the same function should use "your"+"Node" or "their"+"Node" upon conditions - the example is very aproximative, but hope the idea is clear)...
I even did myObj.GetPropertyValue<DynamicNode>("myNode"), but the result was the same: "8124" (the node id)
So, how to obtain the real property value, not just string representation of it?
Your content picker does not contain a node, it contains an id of a node.
myObj.GetPropertyValue("myNode") does exactly what is says, gets the value of a property called myNode on the instantiated DynamicNode object. It is not designed to return the node itself.
If you want to return the node whose ID your 'myNode' property contains then you have to use that value in a call to instantiate another DynamicNode
DynamicNode myNewNode = new DynamicNode(myObj.GetPropertyValue("myNode"))
or
Model.NodeById(myObj.GetPropertyValue("myNode"))
Use somethings like: mynode = Umbraco.Content(CurrentPage.myNode).Url (for Umbraco 6 and 7) For Umbraco 4 i use this Model.NodeById(Model.myNode).Url; in a script file. (I think it need at least Umbraco 4.7.x)
See also https://our.umbraco.org/documentation/Using-Umbraco/Backoffice-Overview/Property-Editors/Built-in-Property-Editors/Content-Picker
A not so elegant solution, but at least a solution that work:
var linkNode = image.GetPropertyValue("imgLinkNode" + model._lang.ToUpper());
if (linkNode is string)
{
string id = linkNode;
linkNode = model.NodeById(id);
}
var linkNodeUrl = linkNode.Url;

Render Node by Id in Umbraco 4.11

TL;DR How do you render a content item by Node Id.
I'm using Widget Grid admin extension for Umbraco to configure a content manageable widget area and I'm stuck trying to render the configured widgets.
I have a list of node id's that I want to render on the page but I can for the life of me work out how to do this.
Any guidance is greatly appreciated! Thanks.
UPDATE
Xml contained within the Models property
<WidgetGrid>
<col1> <nodeId>4839</nodeId> <nodeId>4844</nodeId> <nodeId>4845</nodeId> </col1>
</WidgetGrid>
Once I get down to col1 it seems to cease being of type DynamicXml and just spits it out as a string... No idea.
Presumably you're doing this from within a macro, and I'm going to presume you have a multi-node picker set to store the Id values as CSV:
#{
string[] widgetIds = ((string)Model.Widgets).Split(',');
foreach (var id in widgetIds)
{
var widget = Model.NodeById(id);
#RenderPage("~/macroscripts/widgets/" + widget.NodeTypeAlias
+ ".cshtml", widget);
}
}
This will let you select different types of widget in your multi-node picker, and have a different view for each widget.
This also uses the dynamic approach but you could easily adapt this by swapping the first line for:
string[] podIds = CurrentModel.GetProperty<string>("widgets").Split(',');
Given that the property is stored as XML, you can use the notation as described in this post (http://umbraco.com/follow-us/blog-archive/2011/2/28/umbraco-razor-feature-walkthrough-%E2%80%93-part-3):
foreach (var id in Model.widgets.col1[0].nodeId)
{
...
}

SDL Tridion GetListKeywords using Anquilla Framework

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

Cannot implicitly convert type to List<string>

Afternoon,
I am getting the following error, and cant work out why... Can some one please take a look and let me know where i am going wrong.
Cannot implicitly convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.List'
below is what i am trying to use, to get a list back so i can use it with Amazon. I have tried to remove the .ToList() bit but nothing seems to work. I am calling an MS SQL view "GetASINForUpdateLowPrices" which returns a list back of product ASIN's
List<string> prodASINs = dc.GetASINForUpdateLowPrices.ToList();
SQL for the view i am using, this may help a little bit more.
SELECT asin
FROM dbo.aboProducts
WHERE (asin NOT IN
(SELECT aboProducts_1.asin
FROM dbo.aboProducts AS aboProducts_1 INNER JOIN
dbo.LowestPrices ON aboProducts_1.asin = dbo.LowestPrices.productAsin
WHERE (dbo.LowestPrices.priceDate >= DATEADD(day, - 1, GETDATE()))))
What data type is a single ASIN?
Probably your GetASINForUpdateLowPrices is not an IEnumerable<string>. Try this to confirm:
List<string> prodASINs = dc.GetASINForUpdateLowPrices
.Select(e => e.ToString())
.ToList();
When you call your GetASINForUpdateLowPrices, it wont directly return List<string> even if there is only one field in your view. Try the following approach:
List<string> prodASINs = dc.GetASINForUpdateLowPrices
.Select(item => item.AsinFieldName)
.ToList();
Visual Studio IntelliSense should suggest you the property name after typing item.. If the property is not string try to add .ToString() at the end of the property name.
Edit: After your comment, it seems like you need to use it as .Select(item => item.asin.ToString()).
Just use var.
var prodASINs = dc.GetASINForUpdateLowPrices.ToList();
Are you sure that GetASINForUpdateLowPrices.ToList() creates a List of Strings? My best estimation is that it is a generic list of a different type.
To figure out what is going on - Change List<string> prodASINS to be Object obj. Then set a breakpoint to see what List type is actually generated by your ToList() code by checking out the object using the debugger. You can then update your code to move the values into a list of the appropriate type.
You might have to cast the right side of the assignor like this to ultimately get the job done (replacing string with another type if necessary) - List<string> prodASINs =(List<string>)dc.GetASINForUpdateLowPrices.ToList()

Resources