I have a standard SpringMVC ModelAndView. In one of my model objects I have an ArrayList of objects that I want to have different ui rendering capabilities. (different date formats, different css classes, divs, spans, etc....) Right now my template(view) looks like this:
<c:forEach items="${object.objectList}" var="item">
${item.toHtml}
</c:forEach>
My different items of course generate their own HTML. This of course is very, very wrong as I have html code in my java code which I hate. Is there anyway to have a template(view) for each item? Item is an abstract superclass, and I want each concrete implementation to have it's own view.
This is not a direct solution, but I think that the tutorial here and the corresponding GitHub project here might give you enough of an idea to build the solution yourself. It does not directly address your concern, but it includes a nice little tutorial on custom template tags within a Spring project. In principal, you can create libraries of custom tags, which depending on the parameters you pass them, can create any styled HTML or JavaScript programatically, without having to store the HTML in your database (which can have its own inherent issues).
Related
I am using a Repeater web part in Kentico to pick out pages from the content tree, to generate nicely repeatable snippets of structured HTML, based on an ASCX transformation. (No surprises here - its been working great!).
However, a new requirement landed whereby alongside the existing HTML structure mentioned above, each repeated item must also have an area where we can add any amount of additional content; based on other web parts.
I have previously written a few "layout" type web parts; implementing CMSAbstractLayoutWebPart, as described here, which has allowed me to generate a repeating amount of web part zones, so I feel like I'm half way there. The issue with that though is that as it stands, I don't seem to be able to make use of the great power and flexibility of the transformations on the page type (which I really think I need to do, and seems like it should be possible..).
I thought I may be able to specify the WebPartZone control in the transformation markup directly, like in the following:
<%# Register Src="~/CMSInlineControls/WebPartZone.ascx" TagName="CMSWebPartZone" TagPrefix="cms" %>
<cms:CMSWebPartZone ZoneID="ZoneIDHere" runat="server" />
<div>
<h3><%# Eval("Heading") %></h3>
<p><%# Eval("Summary") %></p>
</div>
But the design view doesn't seem to pick up the web part zone; so I'm assuming the page lifecycle may not allow me to do this as I'd hoped.
So what I would like to know is:
Is it possible to include WebPartZone control in a transformation such that I can then bring in new web parts in Design view?
If not, what is the recommended way to go about this? (If a custom web part is the way to go, I'd like to clone the Repeater web part in the first instance, as many of its existing properties will be needed - but presumably this must still inherit from CMSAbstractLayoutWebPart?
Thanks!
Update
Good point about the editor's experience; I would definitely like to keep this as consistent as possible. The issue for me is that the requirements that drive my data structures are not always fully understood - and are certainly subject to change. Also, they are liable to vary (albeit subtly) across different products. So I've been trying to keep templates and page types more or less the same across the board, and push out the differences into page properties that drive web part config through macros. So given that the transformation approach won't work, I expect a custom web part is the right fit for me.
I shall post my findings!
I think adding a web part zone into transformation is not a right direction as web part zone should be a part of page template (not transformation) in order to utilize it.
I'd probably try to organize my content so each item you currently showing in the repeater has any number of child pages (potentially of a different type) and use something like hierarchical viewer in order to present all of them on the page. It allows using different transformation based on either page type or node level. Another advantage of this approach is that you keep editors experience consistent.
In the end, I was able to use transformation markup to specify the generation of web part zones. I went down the route of creating a custom web part that inherits from CMSAbstractLayoutWebPart, rather than using CMSRepeater web part or similar...
Here's a breakdown of things I needed to do this:
Gave the custom layout-type web part some properties with which to query the content tree, and supply them to a TreeProvider.SelectNodes() method in the web part code once it has initialised (by overriding the OnInit() method)
Gave the web part a TransformationName property so that the raw markup can be retrieved using TransformationInfoProvider.GetTransformation(this.TransformationName)
Used the markup above and resolved macros within it using each node from the node query
Example of macro resolution code (HTML transformations with macros)
protected virtual string ResolveNode(TreeNode node)
{
var resolver = this.ContextResolver.CreateChild();
resolver.AddAnonymousSourceData(node);
return resolver.ResolveMacros(rawTransformationMarkup);
}
Then I go looking for placeholder text in the transformation markup and use the methods available in the CMSAbstractLayoutWebPart parent class(es), as detailed here, to Append() the resolved markup and also call AddZone() as necessary to tap into the response string builder
Summary: The great functionality of the API allowed me to completely avoid the use of any repeater controls. I could generate web part zones as part of the layout web part usual layout generation process.
It would be nice if I could figure out how to resolve the expressions in SCRIPT tags in ASCX transformations to complete the story, but by using HTML transformations I can use the above to accomplish what I need.
It is easy enough to create a partial view, and just as easy to render said view. But what if I want said view to have associated JS local to it? And what if I want this view to be rendered multiple times per page?
Basically take something like a tabbed view of textareas that can be added and deleted dynamically. This is easy enough to make one of.
Now, putting that into a partial view and rendering it would be easy. But What if I wanted the page to hoist multiples of the above "partial view". (Even though its pretty frowned upon to have a partial view with javascript in it.)
Is this feasible in any way? Perhaps partial views are not exactly what I'm looking for?
I don't really have any code because this isn't so much a code related question, as it is an architecture(?)/theory question.
If repeating the same partial view requires the same block of JavaScript to be repeated multiple times for multiple instances of the view on one page, that should indicate to you that you've got design problems going on in your JavaScript. That's code repetition that's begging to be refactored. Your script should be written such that it's designed to be loaded once and work - if you need to refer to the markup of the partial view, do so by using classes rather than IDs and so forth, such that your both your HTML and its associated scripts work as a repeatable module.
I would like to disagree with sphanley. I like to see gadgets as whole objects, wholly functional by itself, so when you use it, you just drag it & drop, and it works without affecting other elements in the page. For that it needs to encapsulate everything it needs, JavaScript, CSS, HTML, etc.
However, instead of embedding JavaScript, it might just call a predefined function in a custom library specific to it, thus minimizing code when multiple gadgets are used in the page. And it will need to use ID selectors, not class or any other, so it does not affect other elements unintentionally.
I am newbie in Tridion. I am looking for some sample code for a TBB to get all components for a component template. I have seen examples of how to get components of a page or from a folder but not for this.
I could get the count by using object.GetListUsingItems(filter).SelectNodes(*).Count in my template, but I need a way to iterate all components and get Title or other attributes of Components.
Please advise.
You cannot get all components for a template in one go, you need to look first at which Schemas are associated with this component template, then get all components for each schema. Be aware of Blueprint contexts when doing this.
I'm slightly confused as to what you're trying to achieve with this, if you want to do this as part of a publishing action you would very quickly end up with massive publish transactions with many components in it.
If you want more attributes than exposed in Lists, then use GetUsingItems instead - but be aware that this is a considerably slower operation with a lot more database interactions than getting a list.
I'm trying to create a custom deployer in Tridion 2011 SP1 that can index a component to a solr instance once published. Everything is working fine but I've come across a bit of a problem with the way it indexes the components fields.
I can access the meta data fields okay by using the Component.getCustomMeta() method and parsing the XML. Accessing the normal fields however does not seem to be possible without reading in the file that is being output and parsing the output. This is not entirely feasible as the markup may change and it seems to be a long way around doing what should (hopefully) be a simple thing.
I've had a trawl through the docs and there doesn't seem to be anything available to get the field values so am I at a loss here and will need to parse the output or am I missing something somewhere?
Content fields are not exposed as such on the delivery side, content is exposed as, not surprisingly, "content".
If you really need the fields, you need to:
Produce a "parseable" output for your component presentations
Parse the component presentations as they get published.
Look at implementations like DD4T for similar approaches.
In short - you cannot do it, because Tridion does not expose it Out of the Box. The only way to do it is by changing the content output format through a template.
We have done an alternative workaround to achieve for the similar requirement. One down side with the implementation is extra rendering of Component Presentations in XML and duplicate of xml storage in broker.
Here is what we have done:
Created a Dynamic CT (XML representation of content) GetComponentAsXML and mapped to all schemas
All the Page Templates has a C# TBB that looks up the content that we need to push to SOLR
C# TBB does the RenderComponentPresentation with above Dynamic CT GetComponentAsXML, this pushes the XML (engine.RenderComponentPresentation(component.Id, componentTemplateURI)
Deployer now gets the content in xml format, in addition to the other type of component presentations (like ascx, emebedded on page etc..)
Hope this information helps.
Hey folks,
I've been learning MVC 2 and I have pretty much everything understood except for the model part of things, I understand what the model is but actually implementing it has me confused.
Here's my situation, I have my DB which has 3 tables;
Ideas - table of ideas
Tags - table of tags
IdeaTag - link table connecting the above 2 tables via FKs
So when using the Entity Framework (.edmx) designer in VS2010 I get 2 classes created in the Designer, which obviously map to my DB tables and Navigation Properties in Idea for Tags & Idea for Tag.
So this is all fine until I actually try to add tags to an idea, what's the best practise for dealing with Navigation Properties? I wanted to add a Textbox which will then map to the Tags property in the Idea class but I'm unsure how I'd go about this.
Most of the MVC tutorials which discuss EF or Linq to SQL are quite basic.
If there are any suggestions for tutorials or video tutorials which discuss dealing Navigation Properties and how best to deal with them I'd gladly take it on board. Alternatively if there is a better way to implement this I'd happily look into that too.
Seeing as this is basically a Many to Many relationship, check out the accepted answer on this question.
It covers the scenario you are looking for. In your case 'ID' is probably the actual tag, i.e. "Entity Framework" or something.
Using the approach in that sample you can have a textbox, with a comma (or something else) delimited list of tag names. Splitting the contents of the textbox gives you an array of tags that should be in the Idea.Tags collection after you're done.
The only complication you have is I guess, you want to automatically create 'new' tags. So perhaps you'll probably need to check whether the Tag exists before attaching it (to add it to the Idea.Tags collection), if it doesn't exist instead of attaching it you would simply add it, so the new tag gets inserted.