Tridion: Component Template issue when looping over linked components - tridion

Hello,
I got a problem with looping over my linked component.
I created a EmailSetup(View UML diagram) Component with a product item.
The product Component has schema (EmailBlockWithCode).
Product: - Code = "wms_III"
- Item: - Key = "ProductKey"- Content = "ProductContent"
- CallToAction : - Item: - Key = "BluetoothKey"
- Content = "BluetoothContent"
When i loop over this component with the code :
<products>
<!-- TemplateBeginRepeat name="Component.Fields.Product" -->
##GetComponent(Field,'Product')##
<product name="##Product.Code##">
<!-- TemplateBeginRepeat name="Product.Fields.Item" -->
<##Product.Fields.Item.Key##><![CDATA[##Product.Fields.Item.Content##]]></##Product.Fields.Item.Key##>
<!-- TemplateEndRepeat -->
<!-- TemplateBeginRepeat name="Product.Fields.CallToAction" -->
##GetComponent(Field,'CallToAction')##
<##CallToAction.Fields.Item.Key##><![CDATA[##CallToAction.Fields.Item.Content##]]></##CallToAction.Fields.Item.Key##>
<!-- TemplateEndRepeat -->
</product>
<!-- TemplateEndRepeat -->
</products>
This is the function GetComponent
[TemplateCallable]
public string GetComponent(string tcmUri, string packageVariable) {
Assert.NotEmpty("tcmUri", tcmUri);
Assert.NotEmpty("packageVariable", packageVariable);
IdentifiableObject identifiableObject = m_Engine.GetObject(new TcmUri(tcmUri));
if (identifiableObject as Component == null) {
throw new BuildingBlockException("Given tcmUri '" + tcmUri + "' is not a Component.");
}
Item previousItem = m_Package.GetByName(packageVariable);
if (previousItem != null) {
m_Package.Remove(previousItem);
}
Component component = identifiableObject as Component;
m_Package.PushItem(packageVariable, m_Package.CreateTridionItem(ContentType.Component, component));
return "";
}
My output is :
<products>
<product name="wms_III">
</product>
</products>
So my problem is that the code doesn't loop over the 'item' (key = ProductKey; content = ProductContent)
I have found a function IteratingOverMultivalueEmbeddedFields but this also won't loop my product. code:
<!-- TemplateBeginRepeat name="Component.Fields.Product" -->
##GetComponent(Field,'Product')##
<!-- TemplateBeginRepeat name="Product.Fields" -->
##Field.Name##
<!-- TemplateBeginRepeat name="Field.Values" -->
<!-- TemplateBeginIf cond="Field.ContentType = 'text/plain'" -->
##RenderComponentField(FieldPath, TemplateRepeatIndex)##
<!-- TemplateEndIf -->
<!-- TemplateBeginIf cond="Field.ContentType = 'tridion/field'" -->
<!-- TemplateBeginRepeat name="Field.Fields" -->
##Field.Name##
<!-- TemplateBeginRepeat name="Field.Values" -->
##RenderComponentField(FieldPath, TemplateRepeatIndex)##
<!-- TemplateEndRepeat -->
<!-- TemplateEndRepeat -->
<!-- TemplateEndIf -->
<!-- TemplateEndRepeat -->
<!-- TemplateEndRepeat -->
UML diagram

So it looks like you can't access the components in the package after your DW function pushes them in?
With the DGX, your code would be approximately like this, have you considered using it instead?
<products>
<!-- TemplateBeginRepeat name="Component.Fields.Product" -->
<product name="##Get('Fields.Product[${TemplateRepeatIndex}].Code')##">
<!-- TemplateBeginRepeat name="Product.Fields.Item" -->
<##Get('Fields.Product[${TemplateRepeatIndex}].Fields.Item.Key')##><![CDATA[##Get('Fields.Product[${TemplateRepeatIndex}].Fields.Item.Content')##]]></##Get('Fields.Product[${TemplateRepeatIndex}].Fields.Item.Key')##>
<!-- TemplateEndRepeat -->
<!-- TemplateBeginRepeat name="Product.Fields.CallToAction" -->
<##Get('Fields.CallToAction[${TemplateRepeatIndex}].Fields.Item.Key')##><![CDATA[##Get('CallToAction[${TemplateRepeatIndex}].Fields.Item.Content')##]]></##Get('Fields.CallToAction[${TemplateRepeatIndex}].Fields.Item.Key')##>
<!-- TemplateEndRepeat -->
</product>
<!-- TemplateEndRepeat -->
</products>

This has probably something to do with how the template is executed. The most inner repeating regions are rendered first, and then the renderer works its way outwards.
So in the inner repeating region you don't have access yet to the component you get earlier.
Yes, this is not intuitive at all, but that's how it works.
What you can do is go through all linked components and push them into the package using the field name in a .NET TBB which is executed before the DWT.
http://80000ft.blogspot.nl/2011/09/render-order-of-repeating-regions-and.html

I fixed this by using this code. Not the best but it works.
<products>
<!-- TemplateBeginRepeat name="Component.Fields.Product" -->
##RenderComponentPresentation(Field, "tcm:75-72162-32")##
<!-- TemplateEndRepeat -->
</products>
and the renderComponentPresentation loads another dwt with this:
<product name="##Component.Fields.Code##">
<!-- TemplateBeginRepeat name="Component.Fields.Item" -->
<##Field.Key##><![CDATA[##Field.Content##]]></##Field.Key##>
<!-- TemplateEndRepeat -->
<!-- TemplateBeginRepeat name="Component.Fields.CallToAction" -->
##GetComponent(Field,'CallToAction')##
<##CallToAction.Fields.Item.Key##><![CDATA[##CallToAction.Fields.Item.Content##]]></##CallToAction.Fields.Item.Key##>
<!-- TemplateEndRepeat -->
</product>

Related

v-snackbar display on top of other components [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 11 months ago.
Improve this question
I have this snack bar, it works perfectly, but it displays under a headerBar.
Sometimes, I have to scroll up to see it. User will missed the important alert message, and don't know what is going on. I'm hoping to display it on top of all other components.
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<template id="mainbox">
<v-container>
<v-row>
<v-col cols="12">
<v-card outlined>
<div class="text-overline mb-4">
{{ title }}
</div>
<!-- -------------------------------------------------------------------------- -->
<div class="py-10"></div>
<!-- -------------------------------------------------------------------------- -->
<!-- TEST CODE -->
<!-- --------- -->
<v-app-bar app color="green lighten-2" dark v-if="showAppBar">
<v-toolbar-title>App Bar </v-toolbar-title>
</v-app-bar>
<v-snackbar transition="true" timeout="2000" v-model="alert" absolute top :color="alertColor" outlined right>
<strong>
{{ alertMessage }}
</strong>
</v-snackbar>
<v-btn color="green lighten-1" #click="doSomething()">
Toggle App Bar
</v-btn>
<!-- -------------------------------------------------------------------------- -->
<div class="py-10"></div>
<!-- -------------------------------------------------------------------------- -->
<!-- END TEST CODE -->
<!-- --------- -->
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<v-app id="app">
<!-- -------------------------------------------------------------------------- -->
<!-- TITLE -->
<!-- ----- -->
<mainbox title="$CODE_08" />
<!-- -------------------------------------------------------------------------- -->
</v-app>
<script type="text/javascript">
const mainbox = Vue.component('mainbox', {
template: '#mainbox',
props: {
title: String
},
data() {
return {
showAppBar: true,
alert: true,
alertColor: 'green',
alertMessage: 'Success Message Test .... !!!! '
}
},
methods: {
doSomething() {
this.showAppBar = !this.showAppBar
this.alert = true,
this.alertColor = 'green',
this.alertMessage = 'test'
}
}
});
new Vue({
el: "#app",
vuetify: new Vuetify(),
components: {
mainbox
}
});
</script>
The v-snackbar by default has a fixed position with a z-index: 1000. With absolute property set, the z-index become 1. So, if there is no absolute need for the absolute prop, remove it and it should solve the problem.

Wordpress Podio Form embedded error

I try to embed my Podio Form in to this wordpress page however it's just show / < ![CDATA[ // < ![CDATA[ // as in the picture above
Here is the code that I used:
[av_textblock size='' font_color='' color='']
[:vi]
[/av_textblock]
[av_codeblock wrapper_element='' wrapper_element_attributes='' custom_class='']
<!-- BEGIN Podio web form -->
<script src="https://podio.com/webforms/15016309/1006763.js"></script>
<script type="text/javascript">// < ![CDATA[
// < ![CDATA[ _podioWebForm.render("1006763")
// ]]></script>
<noscript>
Please fill out the form
</noscript>
<div class="podio-webform-container">A webform by <a class="podio-webform-inner" href="https://company.podio.com/project-management-software">Podio</a></div>
<!-- END Podio web form -->
[/av_codeblock]
[av_textblock size='' font_color='' color='']
[:en]
[/av_textblock]
[av_codeblock wrapper_element='' wrapper_element_attributes='' custom_class='']
<!-- BEGIN Podio web form -->
// < ![CDATA[ // < ![CDATA[ //
<!-- END Podio web form -->
[/av_codeblock]
[av_textblock size='' font_color='' color='']
[:]
[/av_textblock]
Anyone can help me?
You have the form render function commented out and prefixed with < ![CDATA[
You also have it wrapped with [av_codeblock wrapper_element='' wrapper_element_attributes='' custom_class=''] which I'm not sure what that even is; but it might cause rendering issues.
<!-- BEGIN Podio web form -->
<script src="https://podio.com/webforms/12345/6789.js"></script>
<script type="text/javascript">
_podioWebForm.render("6789")
</script>
<noscript>
Please fill out the form
</noscript>
<div class="podio-webform-container">
Get your free webform from Podio
</div>
<!-- END Podio web form -->
From looking at your code snippet, the format of the webform embed code looks different from what we would expect to be generated by Podio. For example, if I export a webform on a demo app the code looks like this:
<!-- BEGIN Podio web form -->
<script src="https://podio.com/webforms/12345678/1234567.js"></script>
<script type="text/javascript">
_podioWebForm.render("1234567")
</script>
<noscript>
Please fill out the form
</noscript>
<div class="podio-webform-container">
Get your free webform from Podio
</div>
<!-- END Podio web form -->
As a starting point, please navigate to your App in Podio, select the wrench icon from the top left, and the select Webform. Enter the domain of your website in the provided field, and copy and paste the provided embed code directly into your Wordpress HTML. Here if a helpful video that walks through this process.

grunt: cdnify doesn't do anything

I have created an AngularJS application using Yeoman. It also uses the cdnify task that shoud transform bower_components/angular/angular.js into //ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js. The generated index.html contains the following code:
<!-- build:js scripts/vendor.js -->
<!-- bower:js -->
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap.js"></script>
<!-- endbower -->
<!-- endbuild -->
There is also a task that combines, minifies and uglifies all the scripts, so these scripts are combined into a single vendor.js file. To avoid jquery.js and angular.js to be included in this process, I changed it into:
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/angular/angular.js"></script>
<!-- build:js scripts/vendor.js -->
<!-- bower:js -->
<script src="bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap.js"></script>
<!-- endbower -->
<!-- endbuild -->
When I run grunt serve:dist the cdnify task is ran and generates the following output:
Running "cdnify:dist" (cdnify) task
Going through dist/404.html, dist/index.html to update script refs
My bower.json looks like this:
{
"name": "myAmazingAngularApp",
"version": "0.0.0",
"dependencies": {
"jquery": "~1.11.0",
"angular": "1.2.x",
"bootstrap": "~3.1.1",
"angular-bootstrap": "~0.10.0"
}
}
Does anyone know what I am doing wrong? I would think it should work out-of-the-box, so I suspect it's a bug...
There is also a .bowerrc file that has the following content:
{
"directory": "app/bower_components"
}
I tried changing this setting to "directory: bower_components" when running grunt cdnify, but it doesn't help.

Inject dependencies into grunt serve index file

so i'm using bower for my packages and grunt serve is as far as i've gone with grunt, what i want to know is, just to save me the time.
how do i get grunt/bower to include what i need either from the command line (would be best for workflow) or using the .json file in the initial index.html file?
so in this case i've ran,
yo webapp(or mobile)
bower install topcoat --save
bower install jplayer --save
bower update
grunt serve
heres my json file
{
"name": "imtoolbox",
"version": "0.0.0",
"dependencies": {
"topcoat": "~0.8.0",
"requirejs": "~2.1.4",
"modernizr": "~2.6.2",
"jquery": "~1.9.1",
"jplayer": "~2.5.5"
},
"devDependencies": {}
}
my head
<link rel="stylesheet" href="styles/main.css">
<!-- build:js scripts/vendor/modernizr.js -->
<script src="bower_components/modernizr/modernizr.js"></script>
<!-- endbuild -->
<!-- build:css styles/vendor/topcoat/css/topcoat-mobile-light.min.css -->
<link rel="stylesheet" href="styles/vendor/topcoat/css/topcoat-mobile-light.min.css">
<!-- endbuild -->
my scripts
<!-- build:js scripts/main.js -->
<script data-main="scripts/main" src="bower_components/requirejs/require.js"></script>
<!-- endbuild -->
<!-- build:js scripts/async-local-storage.js -->
<script src="scripts/async.localStorage.js"></script>
<script src="scripts/async.localStorage.examples.js"></script>
<!-- endbuild -->
<!-- build:js scripts/fullscreensnippet.js -->
<script src="scripts/fullscreensnippet.js"></script>
<!-- endbuild -->
<!-- build:js scripts/fastclick.js -->
<script src="scripts/fastclick.js"></script>
<script src="scripts/fastclick.example.js"></script>
<!-- endbuild -->
any help on this would be great it seams theres a lot of different answers online and having something that works would be sweet!
I think you're missing bower's wiring
<!-- build:js scripts/myscripts.js -->
<!-- bower:js -->
<script src="bower_components/jquery/jquery.js"></script>
<script src="bower_components/sass-bootstrap/dist/js/bootstrap.js"></script>
<!-- endbower -->
<!-- endbuild -->

Layout.css no longer being recognised after change in url for web application

Hi am using Tapestry 5 to create a planning web application and to get around a spring security issue I have changed the url pattern in org.apache.tapestry5.TapestryFilter from /* to /planning/*
After altering the corresponding urls and file paths in any Java / .tml files accordingly the web application works as itended, however my css stylesheet is no longer being picked up.
I have a Layout.java in a components file and a corresponding Layout.tml, and then a layout.css file in a layout folder in the webapp file (outside of WEB-INF)
The stylesheet is being called in the Layout.java file by #Import(stylesheet="context:layout/layout.css") - this always worked before!
I have tried moving the css file into a planning subdirectry planning/layout/layout.css but this still doesnt seem to make a difference!
Web.xml
<display-name>Planning Tapestry 5 Application</display-name>
<context-param>
<param-name>tapestry.app-package</param-name>
<param-value>com.quartetfs.planning.tapestry</param-value>
</context-param>
<filter>
<filter-name>app</filter-name>
<filter-class>org.apache.tapestry5.TapestryFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>app</filter-name>
<url-pattern>/planning/*</url-pattern>
</filter-mapping>
Layout.java
import org.apache.tapestry5.*;
import org.apache.tapestry5.annotations.*;
import org.apache.tapestry5.ioc.annotations.*;
import org.apache.tapestry5.BindingConstants;
/**
* Layout component for pages of Planning Application.
*/
#Import(stylesheet="context:layout/layout.css")
public class Layout
{
/** The page title, for the <title> element and the <h1> element. */
#Property
#Parameter(required = true, defaultPrefix = BindingConstants.LITERAL)
private String title;
#Property
private String pageName;
#Property
#Parameter(defaultPrefix = BindingConstants.LITERAL)
private String sidebarTitle;
#Property
#Parameter(defaultPrefix = BindingConstants.LITERAL)
private Block sidebar;
#Inject
private ComponentResources resources;
public String getClassForPageName()
{
return resources.getPageName().equalsIgnoreCase(pageName)
? "current_page_item"
: null;
}
public String[] getPageNames()
{
return new String[] { "planning/Index", };// "About", "Contact" }; TODO
}
}
Layout.tml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1- strict.dtd">
<!--
Design by Free CSS Templates
http://www.freecsstemplates.org
Released for free under a Creative Commons Attribution 2.5 License
Title : Concrete
Version : 1.0
Released : 20080825
Description: A Web 2.0 design with fluid width suitable for blogs and small websites.
-->
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"
xmlns:p="tapestry:parameter">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>${title}</title>
</head>
<body>
<!-- start header -->
<div id="header">
<div id="logo">
<h1>
<t:pagelink page="planning/index">Project and Resource Planning</t:pagelink>
</h1>
</div>
<div id="menu">
<ul>
<li t:type="loop" source="pageNames" value="pageName" class="prop:classForPageName">
<t:pagelink page="prop:pageName">${pageName}</t:pagelink>
</li>
</ul>
</div>
</div>
<!-- end header -->
<!-- start page -->
<div id="page">
<!-- start sidebar -->
<div id="sidebar">
<ul>
<li id="search" style="background: none;">
</li>
<li t:type="if" test="sidebar">
<h2>${sidebarTitle}</h2>
<div class="sidebar-content">
<t:delegate to="sidebar"/>
</div>
</li>
</ul>
</div>
<!-- end sidebar -->
<!-- start content -->
<div id="content">
<div class="post">
<div class="title">
<h2>${title}</h2>
</div>
<div class="entry">
<t:body/>
</div>
</div>
</div>
<!-- end content -->
<br style="clear: both;"/>
</div>
<!-- end page -->
<!-- start footer -->
<div id="footer">
<p class="legal">
©2009 com.example. All Rights Reserved.
•
Design by
Free CSS Templates
•
Icons by
FAMFAMFAM.
</p>
</div>
<!-- end footer -->
</body>
</html>
You should not have to move the layout.css file; if Tapestry can't find it, then it will throw an exception when loading the pages containing the Layout component.
When you have a problem like this, it is very useful to view the source of the rendered page, and see what the requests and reponses are.
I suspect that the URL for the stylsheet is coming out as "/assets/..." ... which is not picked up by Tapestry (due to how your filter mapping is set up), and you'll see a 404 error.
It is necessary to inform Tapestry that you have placed the application in a sub-folder (alas, the Servlet API does not provide introspection into how you have things configured in your web.xml).
http://tapestry.apache.org/configuration.html#Configuration-tapestry.applicationfolder
Once Tapestry knows the application folder, it can build proper URLs.

Resources