It seems like query datasources (ex: query:...) are not supported in Sitecore 8 MVC while using glass. I want to make a relative path so that branch templates will point to the correct datasource when created. Is there a way to do this with Sitecore's query builder? I saw the custom query option where a path can be specified but couldn't seem to get anything going. I think I might add a pipeline processor before the model gets bound by glass to change a datasource that starts with query: into a resolved path and pass that along the pipeline arguments.
You can add a datasource query to a Sublayout or Rendering Datasource Layout field. You will need to add a new Processor to the getRenderingDatasource Pipeline. I myself have used this on Branch Templates to make relative paths to the correct datasource.
Your query:. needs to be defined in the Datasource Location of the sublayout/rendering and make use of ancestor-or-self to make relative paths and traverse the tree to find the parent item holding the datasources.
query:.ancestor-or-self:: *[##templatename = 'home']/*[##templatename = 'storage']/*[##templatename = 'articles']
The processor will need to use the GetRenderingDatasourceArgs. These arguements will provide you pretty much everything you need. Essentially you will need to get the query:. you wrote in the Datasource Locations.
args.RenderingItem["Datasource Location"];
Replace the beginning of the query with the Context Item path (so that its relative) and then make a call to get the items;
private IEnumerable<Item> GetDatasourceLocationsFromQuery(string query)
{
string queryPath = query.Replace("query:.", args.ContextItemPath);
return args.ContextDatabase.SelectItem(queryPath);
}
This will then return the matching item that is the parent of the datasources.
Related
My Content structure is:
-Home (the site root node)
-About Us
-Our Sevice1
-Our Sevice2
-Our Sevice3
I created a macro for Our Services.
In macro, I want Our Sevice1, Our Sevice2, Our Sevice3...
But in the list variable About Us also come but I don't want it
I want only our service name of the child node
var list= CurrentPage.Children();
About Us also come on the list but I don't want it.
The reason that you see the About Us page in the collection is because you use the Children method.
With the Children method you ask for the direct child nodes of a parent node traversing one level down. So in this case you ask for all direct children of the home page so this works like expected.
What you are trying to achieve is a collection of of all Service nodes. To accomplish this you could do something like this.
Make sure that you have a seperated Document Type for your service nodes ( like for example doc type Service Page ).
Then you can do the following:
var servicePages = CurrentPage.ServicePages;
You can view the docs about it here:
https://our.umbraco.org/documentation/reference/querying/dynamicpublishedcontent/collections
But all of this is using dynamic syntax, this will be removed in future versions of Umbraco. So I suggest you go and use the strongly type syntax.
Then this can be changed by:
var servicePages = Model.Content.Children.Where(x => x.DocmentTypeAlias == "servicePage");
What this does is take the IPublishedContent object of the current page you are on, which is the Home Page then you take all children which has a document type alias of type servicePage.
Like #Mivaweb mentioned, it's better to not use dynamics (I think for performance in addition to being removed in the future).
However, I don't think you have to create a separate doc type, although that will work too. The predicate for the Where method should handle other expressions such as:
var servicePages = Model.Content.Children.Where(x => x.Name.StartsWith("Our Sevice"));
We're in the process of moving to DTM implementation. We have several variables that are being defined on page. I understand I can make these variables available in DTM through data elements. Can I simply set up a data elem
So set data elements
%prop1% = s.prop1
%prop2% = s.prop2
etc
And then under global rules set
s.prop1 = %s.prop1%
s.prop2 = %s.prop2%
etc
for every single evar, sprop, event, product so they populate whenever they are set on a particular page. Good idea or terrible idea? It seems like a pretty bulky approach which raises some alarm bells. Another option would be to write something that pushes everything to the datalayer, but that seems like essentially the same approach with a redundant step when they can be grabbed directly.
Basically I want DTM to access any and all variables that are currently being set with on-page code, and my understanding is that in order to do that they must be stored in a data element first. Does anyone have any insight into this?
I use this spec for setting up data layers: Data Layer Standard
We create data elements for each key that we use from the standard data layer. For example, page name is stored here
digitalData.page.pageInfo.pageName
We create a data element and standardize the names to this format "page.pageInfo.pageName"
Within each variable field, you access it with the %page.pageInfo.pageName% notation. Also, within javascript of rule tags, you can use this:
_satellite.getVar('page.pageInfo.pageName')
It's a bit unwieldy at times but it allows you to separate the development of the data layer and tag manager tags completely.
One thing to note, make sure your data layer is complete and loaded before you call the satellite library.
If you are moving from a legacy s_code implementation to DTM, it is a good best practice to remove all existing "on page" code (including the reference to the s_code file) and create a "data layer" that contains the data from the eVars and props on the page. Then DTM can reference the object on the page and you can create data elements that map to variables.
Here's an example of a data layer:
<script type="text/javascript">
DDO = {} // Data Layer Object Created
DDO.specVersion = "1.0";
DDO.pageData = {
"pageName":"My Page Name",
"pageSiteSection":"Home",
"pageType":"Section Front",
"pageHier":"DTM Test|Home|Section Front"
},
DDO.siteData = {
"siteCountry":"us",
"siteRegion":"unknown",
"siteLanguage":"en",
"siteFormat":"Desktop"
}
</script>
The next step would be to create data elements that directly reference the values in the object. For example, if I wanted to create a data element that mapped to the page name element in my data layer I would do the following in DTM:
Create a new data element called "pageName"
Select the type as "JS Object"
In the path field I will reference the path to the page name in my data layer example above - DDO.pageData.pageName
Save the data element
Now this data element can be referenced in any variable field within any rule by simply typing a '%'. DTM will find any existing data elements and you can select them.
I also wrote about a simple script you can add to your implementation to help with your data layer validation.Validate your DTM Data Layer with this simple script
Hope this helps.
Trying to figure out how to extend entities that I query from breeze.js on a per-view basis in a single page application. Right now breeze is acting as the gate-keeper when it comes to extending (a.k.a materializing) them and I’m wondering what other options are available to allow me to do this. I initially started with knockout’s mapping plugin but found that it refused to handle child collections for some reason so I moved to using breeze’s constructor function and initializer methodology. The problem with this is that you can only define one custom "model" for an entity. I am looking for approaches that would allow a custom "model" of an entity on a per-view basis. I’ve already ruled out multiple managers. Querying meta-data multiple times is a huge unnecessary hit just to get this working.
This diagram visualizes what I’m trying to achieve. Both View 1 and View 2 ultimately query Entity B and both views require their own specific customization of the "model" of Entity B. Since View 1 loads first it’s custom "model" of Entity B "wins" and View 2 doesn’t have the opportunity to customize it. When View 2 eventually runs it’s query, any entities of type B that were already loaded by View 1 will have the custom "model" that View 1 defined which will make View 2 explode during binding. Any entities not already loaded by View 1 will now have View 2's custom "model" which would eventually crash View 1 if it could even get that far down the road. See this post.
My thought was to manually create my own custom "model" for each view that has an Entity observable and I could then iterate over every entity returned from a breeze query and new up this custom "model" and pass in the current item, assigning it to the Entity property. I don't really want to do this because I now have I'll have tons of iteration code everywhere and I'd much rather use knockout's mapping plugin. Pseudo code:
function view1EntityBModel(entity) {
var self = this;
self.Entity = ko.observable(entity);
self.myCustomProperty = ko.observable();
...
}
function view2EntityBModel(entity) {
var self = this;
self.Entity = ko.observable(entity);
self.isExpanded = ko.observable(false);
...
}
I was wondering if there are any other solutions available to achieve this same goal?
Or even better does anyone know how to make the knockout mapping plugin working on child collections?
I think the problem here is that by the time the mapping plugin gets a-hold of the breeze data the Children collection has already been converted into an observable array and the mapping plugin doesn't know that it needs to "call" the Children() property in order to get back a list.
var categoryMapper = {
create: function (options) {
return new categoryModel(options.data);
},
Children: { // this doesn't fire for the children
create: function (options) {
return new categoryModel(options.data);
}
}
}
function categoryModel(data) {
var self = this;
ko.mapping.fromJS(data, {}, self);
}
Guessing that you've moved on by now, but thought I'd offer a recommendation for others in a similar position.
Our solution to a similar situation borrows from the breeze.js TempHire sample solution which implements a client side repository/uow pattern. The solution uses an EntityMananagerProvider to manage multiple EntityManagers. The EntityMananagerProvider makes a single call for metadata, which is then used to create new child EntityManagers - satisfying your concern regarding multiple metadata calls. You can then use custom models/uow/repositories to extend the child manager for specific views.
I develop web part with custom editor part and faced with this question.
Is it possible in web part set Personalizable attribute to generic List?
For example I want something like this:
[WebBrowsable(false)]
[Personalizable(PersonalizationScope.Shared)]
public List<AnnouncementItem> Announcements
{
get { return _announcements; }
set { _announcements = value; }
}
Is it possible, and what kind of types at all can be used as "Personalizable"?
Thanks.
Solution:
I use a custom EditorPart to select multiple lists using AssetUrlSelector, but I need a way to personalize this collection for end user.List<of custom objects> doesn't work, but I found that List<string> (and only string) work perfectly. So, I get required lists in EditorPart and pass their to the web part using List<string>.
Try using a custom EditorPart to add/remove items from the collection. I've never built a web part that personalized a collection so I don't know if it works but I'd definitely try the collection with an EditorPart. If it doesn't work, serialize XML into a string property.
Your question does not seem to match your code. Your code shows a collection of custom objects. I doubt an end user will be able to set such a property. To have a property that points to a generic list, you would probably be better off defining the property as a string that contains the URL to a list.
I'm working on an application at the moment in ASP.NET MVC which has a number of look-up tables, all of the form
LookUp {
Id
Text
}
As you can see, this just maps the Id to a textual value. These are used for things such as Colours. I now have a number of these, currently 6 and probably soon to be more.
I'm trying to put together an API that can be used via AJAX to allow the user to add/list/remove values from these lookup tables, so for example I could have something like:
http://example.com/Attributes/Colours/[List/Add/Delete]
My current problem is that clearly, regardless of which lookup table I'm using, everything else happens exactly the same. So really there should be no repetition of code whatsoever.
I currently have a custom route which points to an 'AttributeController', which figures out the attribute/look-up table in question based upon the URL (ie http://example.com/Attributes/Colours/List would want the 'Colours' table). I pass the attribute (Colours - a string) and the operation (List/Add/Delete), as well as any other parameters required (say "Red" if I want to add red to the list) back to my repository where the actual work is performed.
Things start getting messy here, as at the moment I've resorted to doing a switch/case on the attribute string, which can then grab the Linq-to-Sql entity corresponding to the particular lookup table. I find this pretty dirty though as I find myself having to write the same operations on each of the look-up entities, ugh!
What I'd really like to do is have some sort of mapping, which I could simply pass in the attribute name and get out some form of generic lookup object, which I could perform the desired operations on without having to care about type.
Is there some way to do this to my Linq-To-Sql entities? I've tried making them implement a basic interface (IAttribute), which simply specifies the Id/Text properties, however doing things like this fails:
System.Data.Linq.Table<IAttribute> table = GetAttribute("Colours");
As I cannot convert System.Data.Linq.Table<Colour> to System.Data.Linq.Table<IAttribute>.
Is there a way to make these look-up tables 'generic'?
Apologies that this is a bit of a brain-dump. There's surely imformation missing here, so just let me know if you'd like any further details. Cheers!
You have 2 options.
Use Expression Trees to dynamically create your lambda expression
Use Dynamic LINQ as detailed on Scott Gu's blog
I've looked at both options and have successfully implemented Expression Trees as my preferred approach.
Here's an example function that i created: (NOT TESTED)
private static bool ValueExists<T>(String Value) where T : class
{
ParameterExpression pe = Expression.Parameter(typeof(T), "p");
Expression value = Expression.Equal(Expression.Property(pe, "ColumnName"), Expression.Constant(Value));
Expression<Func<T, bool>> predicate = Expression.Lambda<Func<T, bool>>(value, pe);
return MyDataContext.GetTable<T>().Where(predicate).Count() > 0;
}
Instead of using a switch statement, you can use a lookup dictionary. This is psuedocode-ish, but this is one way to get your table in question. You'll have to manually maintain the dictionary, but it should be much easier than a switch.
It looks like the DataContext.GetTable() method could be the answer to your problem. You can get a table if you know the type of the linq entity that you want to operate upon.
Dictionary<string, Type> lookupDict = new Dictionary<string, Type>
{
"Colour", typeof(MatchingLinqEntity)
...
}
Type entityType = lookupDict[AttributeFromRouteValue];
YourDataContext db = new YourDataContext();
var entityTable = db.GetTable(entityType);
var entity = entityTable.Single(x => x.Id == IdFromRouteValue);
// or whatever operations you need
db.SubmitChanges()
The Suteki Shop project has some very slick work in it. You could look into their implementation of IRepository<T> and IRepositoryResolver for a generic repository pattern. This really works well with an IoC container, but you could create them manually with reflection if the performance is acceptable. I'd use this route if you have or can add an IoC container to the project. You need to make sure your IoC container supports open generics if you go this route, but I'm pretty sure all the major players do.