If condition within a #foreach loop of Advanced Print View

jdow
Advocate
Advocate

If condition within a #foreach loop of Advanced Print View

jdow
Advocate
Advocate

Hello,

I've created an Advanced Print View that includes grid data.  What I'd like to be able to do is to put within the #foreach loop an if statement that only executes if the property value call DATE_COMPLETED is null.  What I'm having difficulty with is the syntax/formatting of the If statement within the #foreach loop...nothing i've tired works - actually what I put in is alway removed by the IDE upon save.  Is what i'm trying to do possible, is so please provide some guidance.  

I've included the code segment and added may comments in bold letters in the code.

Thank you!

JD

 

 

<table>
<tbody>
<tr><th class="header" colspan="7">${workspace.metadata.grid.title.value}</th></tr>
<tr><th><span>${workspace.metadata.grid.fields.COURSES.title}</span></th><th><span>${workspace.metadata.grid.fields.DATE_DUE.title}</span></th><th><span>${workspace.metadata.grid.fields.DATE_COMPLETED.title}</span></th><th>Employee Signature</th><th>Trainer</th><th>Trainer Signature</th><th>Date Verified</th></tr>
<!-- #foreach( $grid in $item.grid.rows ) -->

ONLY EXECUTE THESE LINES if DATA_COMPLETE IS = NULL
<tr>
<td>${grid.COURSES.value}</td>
<td>${grid.DATE_DUE.value}</td>
<td>${grid.DATE_COMPLETED.value}</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>

END
<!-- #end --></tbody>
</table>

JD
Reply
1,374 Views
12 Replies
Replies (12)

martin.foral
Explorer
Explorer

I have the same request. After 7 years I hope that Autodesk already knows :-). 

philipfrench
Collaborator
Collaborator

Like this...?

The row is only written when DATE_COMPLETED is empty.

pic1.jpg

 

 

<div class="grid">
<table>
<tbody>
<tr>
<th class="header" colspan="4">${workspace.metadata.grid.title.value}</th>
</tr>
<tr>
<th>${workspace.metadata.grid.fields.rowID.title}</th>
<th>${workspace.metadata.grid.fields.COURSE.title}</th>
<th>${workspace.metadata.grid.fields.DUE_DATE.title}</th>
<th>${workspace.metadata.grid.fields.DATE_COMPLETED.title}</th>
</tr>
<!-- #foreach( $grid in $item.grid.rows ) -->
  <!-- #if( ${grid.DATE_COMPLETED.value} == "") -->
    <tr>
      <td>${grid.rowID.value}</td>
      <td>${grid.COURSE.value}</td>
      <td>${grid.DUE_DATE.value}</td>
      <td>${grid.DATE_COMPLETED.value}</td>
    </tr>
  <!-- #end -->
<!-- #end --></tbody>
</table>
</div>

 

The "tr" block is wrapped with an IF-END statement, which is only true when the value is empty.

 

 

Or another example, using IF-ELSE-END:

pic2.jpg

 

<div class="grid">
<table>
<tbody>
<tr>
<th class="header" colspan="4">${workspace.metadata.grid.title.value}</th>
</tr>
<tr>
<th>${workspace.metadata.grid.fields.rowID.title}</th>
<th>${workspace.metadata.grid.fields.COURSE.title}</th>
<th>${workspace.metadata.grid.fields.DUE_DATE.title}</th>
<th>${workspace.metadata.grid.fields.DATE_COMPLETED.title}</th>
</tr>
<!-- #foreach( $grid in $item.grid.rows ) -->
  <!-- #if( ${grid.DATE_COMPLETED.value} == "") -->
    <tr>
      <td>${grid.rowID.value}</td>
      <td>${grid.COURSE.value}</td>
      <td>${grid.DUE_DATE.value}</td>
      <td></td>
    </tr>
  <!-- #else -->
    <tr style="background-color:green;">
      <td>${grid.rowID.value}</td>
      <td>${grid.COURSE.value}</td>
      <td>${grid.DUE_DATE.value}</td>
      <td>${grid.DATE_COMPLETED.value}</td>
    </tr>
  <!-- #end -->
<!-- #end --></tbody>
</table>
</div>

 

TBH I have no idea whether this is supported. But you can google for "velocity macro if else end" and find some examples.

john.denner
Advocate
Advocate

So I've actually done quite a bit of work in APVs, but it's been awhile, so hopefully this still works.
The editor will 100% strip out anything it doesn't deem as valid HTML/XHTML. But we can (or have been able to in the past) get around that by wrapping it all in a CDATA tag and using pure JavaScript (ES5.1). More specifically, an IIFE (Immediately Invoked Function Expression). Placing this at the bottom of your APV code should help ensure that the DOM is loaded first before the script executes. Otherwise, you will get some wacky results depending on if the DOM loaded before the script executed. This method also allows you to not have to use inline scripting, which keeps your HTML cleaner, easier to maintain, and more readable.

 

The following code is based on my failing memory but should hopefully get you close. Text wrapped in CDATA shouldn't get stripped. 🤞

 

 

<script type="text/javascript">// <![CDATA[
(function () {
    item.grid.rows.forEach(function(row) {
        if(row !== null) {
            <Do your thing here>;
        } else {
            <Do something else>;
        }
    }
)();
// ]]></script>

 

0 Likes

john.denner
Advocate
Advocate

Sorry, and one more thing. The APV preview is misleading. You'll need to fully publish to view the end result. Then use the developer tools to see what (if anything) was stripped.

0 Likes

philipfrench
Collaborator
Collaborator

All John's comments (based on more knowledge than me) are correct.

But note my solution uses velocity tags, not javascript.

 

The screenshot are launched from the proper page, not test mode.

 

You should be able to reproduce my solution with a 3 column grid, and pasting in the code to the APV source. Contact me directly if you're struggling.

 

I imagine Autodesk are intending with the stripping of script, that F3M should never be able to serve a page with malicious scripting. Whether you agree with the way that it is implemented or not, you know their intent, and clever ways to defeat this security check may not work forever. So it's an obvious risk to try to still use script tags, although you may feel it is justified by your requirements, which is your call.

The velocity tags get evaluated on the server side, the result is pure html, so will not be subject to script-stripping, and will work in non-javascript client such as a mail body.

martin.foral
Explorer
Explorer

Guys. Thank you so much. I have tried the way by @philipfrench  because it was easier for me :-). Everything works well.  I will try another way later. I am interested in it because our customer wants to mine maximum from APV and sometimes we are lost. This solving is perfect

 

I will have to find out more about velocity macro. I ve never heard about it before. 

 

Does anybody know what is background in APV?

Is there more posibilities to configure output?

I explored the source code after rendering and I found out there is link to jquery.

 

Thanks a lot.

 

Martin

0 Likes

philipfrench
Collaborator
Collaborator

Apache Velocity is a templating language that was built for Java. The backend of F360M is apparently built in java, judging by exception traceback, and I'm guessing they decided to make the APV using Velocity.

 

In the standard articles you can select, I recognised the Velocity format, so I thought I would try to use it.

 

I never read anything that encouraged implementers to use it, so I don't imagine it is supported. However it is not stripped out, and javascript definitely is.

 

With a little imagination, you can loop through the Context (data set) that is passed in, and see the entirety of what is available to use as substitutions.

 

0 Likes

martin.foral
Explorer
Explorer
Philip Thank you so much for clarification.
0 Likes

Aron_Thorfinnsson
Enthusiast
Enthusiast

Trying to apply @philipfrench recommendations without success, here is a snippet of my code:

 

<table style="height: 45px; width: 100%;">
<tbody>
<tr style="height: 16px;">
<th class="header" style="height: 16px; width: 1285.41px; background-color: black;" colspan="3"><span style="color: #ffffff;">Document List</span></th>
</tr>
<tr style="height: 16px;">
<th style="height: 16px; background-color: black; width: 10%;"><span style="color: #ffffff;">${workspace.metadata.linkedItems.fields.NO.title}</span></th>
<th style="height: 16px; background-color: black; width: 75%; text-align: left;"><span style="color: #ffffff;">${workspace.metadata.linkedItems.fields.ITEM.title}</span></th>
<th style="height: 16px; background-color: black; width: 15%;"><span style="color: #ffffff;">${workspace.metadata.linkedItems.fields.LAST_ACCEPTANCE_CODE.title}</span></th>
</tr>
<!-- #foreach( $linkedItem in $item.linkedItems.rows ) -->
   <!-- #if( ${linkedItem.WSID.value} == "144") -->
    <tr style="height: 13px;">
        <td>${linkedItem.NO.value}</td>
        <td>${linkedItem.ITEM.value}</td>
        <td>${linkedItem.LAST_ACCEPTANCE_CODE.value}</td>
    </tr>
    <!-- #end -->
<!-- #end --></tbody>
</table>

 

The APV doesn't return any linkedItem. However it does if I ommit  <!-- #if( ${linkedItem.WSID.value} == "144") --> and its end statement.

Any idea why I cannot get it to work for me?

0 Likes

philipfrench
Collaborator
Collaborator

I tested your example, and it worked for me.

Note that the WSID and LAST_ACCEPTANCE_VALUE are custom fields in the Managed Items tab that I added (see pic below).

The APV can only access the fields from the row in the Managed Items tab. (eg NO, ITEM, and any custom fields).

You cannot access the fields on the actual item, i.e. fields that are in your workspace 144.

 

You would need to use the workflow script to populate this custom WSID value. I suspect this is your issue?

 

 

 

If you do need an APV that includes values from the linked workspaces, then you need to use the workflow script, and collect these fields during the release step, store them in a paragraph field in the CO itself. Then after release, you can perhaps access these in your APV, but obviously this does not work before that workflow step has run.

 

Another alternative is to use the release workflow script to build an HTML string to represent the formatted table itself, and then store this in a paragraph field on the CO.

Your APV can simply refer to this field, and the HTML from the paragraph field will appear in the APV.

 

apv.png

 

 

 

 

Aron_Thorfinnsson
Enthusiast
Enthusiast

Guess I misunderstood the basics of it by assuming the foreach loop somehow loaded its members as objects and thus would be able read fields from the presumably loaded objects - duhh! 

 

Added the wsID as a hidden field in Managed Item and then it works like a charm. Thank you very much for the help.

0 Likes

philipfrench
Collaborator
Collaborator

Good. Use this general approach to interrogate/debug the fields available on a variable.

 

apv2.png