我有一个页面模板,在页面底部的div中输出三个组件演示文稿。所有这三个组件演示文稿都使用相同的模式和Dreamweaver组件模板。
我想根据它们是该div中的第一个组件还是最后一个组件 - 这些组件演示文稿的样式略有不同 - 基本上我想为每个组件添加“first”和“last”CSS类介绍
我正在尝试在模板构建块中动态设置组件表示的“参数”。以下是我到目前为止所做的事情(不起作用,只是为了让你了解我正在尝试做什么):
public override void Transform(Engine engine, Package package)
{
var page = GetPage();
var wantComponents =
from c in page.ComponentPresentations
where c.ComponentTemplate.Title == "Content highlight"
select c;
if (wantComponents.Count() > 0)
{
// pseudocode - won't compile!
wantComponents.First().ComponentTemplate.Parameters["myCssClass"] = "first";
wantComponents.Last().ComponentTemplate.Parameters["myCssClass"] = "last";
}
...
在我的Dreamweaver模板中(再次,不起作用,只是为了让您了解我正在尝试做什么):
<div class="block @@Parameters.myCssClass@@">
...
</div>
如何动态地将“第一”CSS类添加到页面上的第一个组件表示,将“最后”CSS类添加到页面上的最后一个组件表示?
答案 0 :(得分:6)
乔治并不是一个糟糕的问题。
如果从组件模板中取出div并将它们放入页面模板,则无需将页面模板中的参数传递给组件模板。然后将CSS类设置为第一个组件演示很简单:
<div class="<!-- TemplateBeginIf cond="TemplateRepeatIndex==0" -->myFirstCssClass<!-- TemplateEndIf -->"></div>
在最后一个Component Presentation上设置一个类更有趣,有几种方法可以实现:
<!-- TemplateBeginRepeat name="Components" --><div class="<!-- TemplateBeginIf cond="TemplateRepeatIndex==TemplateRepeatCount()-1" -->lastCssClass<!-- TemplateEndIf -->">@@RenderComponentPresentation()@@</div><!-- TemplateEndRepeat -->
。 上面的#1和#2都在我的文章中描述:http://www.tridiondeveloper.com/more-fun-with-dreamweaver-templates-templaterepeatcount
最后,这里有一个更内联的方法,特别是你在询问组件模板实际查找到页面范围的位置,以确定它是否是列表中的最后一个组件表示。这不是我最喜欢的,因为使用TemplateBuilder进行调试并不容易(因为当你通过CT运行时,你没有PT,因此在这个范围内不存在组件表示计数。)
public class IsLastCP : TemplateBase
{
private string MY_SCHEMA = "My Component's Schema Title";
public override void Transform(Engine engine, Package package)
{
this.Initialize(engine, package);
//in the page template.
Page page = this.GetPage();
if (page == null)
{
//this TBB is being executed either in Template Builder or a dynamic component presentation.
// so we just don't do anything.
}
else
{
IList<ComponentPresentation> cpList = page.ComponentPresentations;
int cpCount = 0;
int thisCPIndex = -1;
Component thisComponent = this.GetComponent();
foreach (ComponentPresentation cp in cpList)
{
Component comp = cp.Component;
if (comp.Schema.Title == MY_SCHEMA)
{
if (comp.Id.Equals(thisComponent.Id))
thisCPIndex = cpCount;
cpCount++;
}
}
if (thisCPIndex == cpCount-1)
{
package.PushItem("IsLastCP", package.CreateStringItem(ContentType.Text, "true"));
}
}
}
为此你需要Will着名的TemplateBase类,你可以从他的SDLTridionWorld提供的“有用的Building Blocks”扩展中获得。显然,您需要调整我提供给您的模式名称的代码等。
在您的组件模板中将此TBB放在Dreamweaver TBB之前,然后使用其输出:<!-- TemplateBeginRepeat name="IsLastCP" -->class="myLastCSSClass"<!-- TemplateEndRepeat -->
注意:您不需要在此处执行TemplateBeginIf并在IsLastCP上明确检查true / false。如果有问题的CP是最后一个,那么该变量将出现在包中,并且TemplateBeginRepeat子句将进入。
答案 1 :(得分:0)
你也可以使用Context Variables来做这种事情。您无法直接从DWT执行此操作,因此这可能意味着编写函数源,或者可能使用写入输出的程序集TBB替换DWT。如果这种方法适合您的设计,您可以从页面模板中将变量写入engine.PublishingContext.RenderContext.ContextVariables
,指示Component渲染是否是第一个,然后让组件模板读取它以确定要生成的输出。
通常,我们的想法是在页面模板中编写变量并在组件模板中读取它们。这应该足以让您避免将组件模板问题移到页面模板中,当然,管道的数量可能会让您失望。对于更极端的情况,它可能to get values from the component template to the page template,但是你有更多的管道,所以想要这样做可能是一种设计气味。