如何将参数传递给组件(Dreamweaver)模板?

时间:2012-06-25 01:51:05

标签: tridion

我有一个页面模板,在页面底部的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类添加到页面上的最后一个组件表示?

2 个答案:

答案 0 :(得分:6)

乔治并不是一个糟糕的问题。

如果从组件模板中取出div并将它们放入页面模板,则无需将页面模板中的参数传递给组件模板。然后将CSS类设置为第一个组件演示很简单:

<div class="<!-- TemplateBeginIf cond="TemplateRepeatIndex==0" -->myFirstCssClass<!-- TemplateEndIf -->"></div>

在最后一个Component Presentation上设置一个类更有趣,有几种方法可以实现:

  1. 自定义Dreamweaver函数,例如TemplateRepeatCount()。然后你可以在你的页面模板中做这样的事情: <!-- TemplateBeginRepeat name="Components" --><div class="<!-- TemplateBeginIf cond="TemplateRepeatIndex==TemplateRepeatCount()-1" -->lastCssClass<!-- TemplateEndIf -->">@@RenderComponentPresentation()@@</div><!-- TemplateEndRepeat -->
  2. 另一种方法是编写一个基本的TBB,它会对组件演示进行计数并将总数减少到包中,然后您可以将TemplateRepeatIndex与此数字进行比较。
  3. 上面的#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,但是你有更多的管道,所以想要这样做可能是一种设计气味。