4

I am building a navigation with the VHS Menu ViewHelper. Below is the entire code. My question is probably very basic fluid though.

Inside a scope, how do I access a variable that exists outside that scope - or how do I pass it into that scope?

EDIT: I've updated my code to not use dashes in variable names as well as assigned different names to v:page.menu with as="menuLevel0".


The full code:

{namespace v=Tx_Vhs_ViewHelpers}
<ul id="nav" class="grid-full classic">
    <v:page.menu as="menuLevel0" expandAll="1" useShortcutData="1" levels="4" classHasSubpages="parent" classFirst="first" classLast="last">
        <f:for each="{menuLevel0}" as="itemLevel0" iteration="iterLevel0">
            <li class="{itemLevel0.class} level0 nav-{iterLevel0.cycle} level-top">
                <a href='{itemLevel0.link}' class='level-top'><span>
                    <f:if condition="{itemLevel0.nav_title}"><f:then>{itemLevel0.nav_title}</f:then><f:else>{itemLevel0.title}</f:else></f:if>
                nav-{iterLevel0.cycle}</span>
                </a>
                <f:if condition="{itemLevel0.hasSubPages}">
                    <f:then>
                        <v:page.menu as="menuLevel1" expandAll="1" classHasSubpages="parent" classFirst="first" classLast="last">
                            <ul class="level0">
                                <f:for each="{menuLevel1}" as="itemLevel1" iteration="iterLevel1">
                                    <li class="{itemLevel1.class} level1 nav-{iterLevel0.cycle}-{iterLevel1.cycle}">
                                        <a href='{itemLevel1.link}' class='level-top'><span>
                                            <f:if condition="{itemLevel1.nav_title}"><f:then>{itemLevel1.nav_title}</f:then><f:else>{itemLevel1.title}</f:else></f:if>
                                            nav-{menuLevel0.iterLevel0.cycle}-{iterLevel1.cycle}
                                        </span></a>
                                    </li>
                                </f:for>
                            </ul>
                        </v:page.menu>
                    </f:then>
                </f:if>
            </li>
        </f:for>
    </v:page.menu>
</ul>
Urs
  • 4,984
  • 7
  • 54
  • 116
  • I just noticed it's only not working for the first item of the main section. – Urs Feb 18 '14 at 15:40
  • and it works with page.menu.directory, see https://github.com/FluidTYPO3/vhs/issues/479 – Urs Feb 21 '14 at 12:25
  • You seem to have a misconception about how to access variables from parent scope. You dont actually need to use ``{menuLevel0.iterLevel0.cycle}``. ``{iterLevel0.cycle}`` is enough. – Cedric Ziel Feb 23 '14 at 14:30
  • That's what I've been doing all the way ... Now, the only difference is that I set `{iterLevel0.cycle}`still returns NULL instead of 1 for the first item (in the parent level, when accessing it from the child level): https://dl.dropboxusercontent.com/u/11320047/iter.png . I've started thinking it might be a bug, either in `f:for`or in `v:page.menu`. – Urs Feb 23 '14 at 19:09

4 Answers4

2

In fluid, variables are and should be scoped to the blocks you are using.

While you are using our v:page.menu ViewHelpers, you need to understand the scoping a bit further:

  1. Use different names for variables in nested scopes: {levelOneIterator} and {levelTwoIterator} are good examples for such behaviour
  2. As a rule of thumb: Use lowerCamelCased variable names. It prevents fluid from parsing your var-names wrong.

The reason why your code is not working:

You assign a {iter} variable. Therefore fluid doesn't parse the dash-ified variable name as it detects the undashified identifier first. Dashes have special meaning in fluid and you can run into kind-of race conditions there.

To take this a bit further:

``` {foo-bar} // echos "baz" {foo-bar} // echos "bing", as the bar vaiable is read first, and "foo-" isnt a variable in the current scope

```

Update:

Accessing variables from a parent scope doesnt require prefixing your var-call. In a child for-loop, you can access the parent iteration by simply calling the var.

<f:for each="{iterable}" as="iterableItem iteration="iteratorRoot"> {iteratorRoot.index} <!-- Echoes the current, zero-indexed iteration --> <f:for each="{iterableItem}" as="subItem" iteration="iterationChild"> <!-- STILL echoes the current, zero-indexed iteration --> {iteratorRoot.index} <!-- Echoes the current, zero-indexed sub iteration --> {iterationChild.index} </f:for> </f:for>

As long as you give different names to the iterators, you can access them in any scope by their originating name. Same goes for the aliased (as="name") named variables.

Community
  • 1
  • 1
Cedric Ziel
  • 1,052
  • 8
  • 21
  • Thanks again, Cedric. I've updated my question above. I'm getting there. But still I don't see how I can access the parent scope (or something like a global variable) or pass in the desired variable from the parent scope into the child scope to use there. That must be possible, isn't it? – Urs Feb 23 '14 at 08:49
  • I've also tried ``and in the child scope `{menuLevel0iter}`- but of course the scope isnt global either – Urs Feb 23 '14 at 08:51
1

Try not using "-" in the variable-name! Use CamelCase instead:

<f:render section="layer2" arguments="{uid: curPage.uid, parentIter: iter.cycle}" />
thismaechler
  • 201
  • 2
  • 3
1

In Controller

public function listAction() {
    $events = $this->eventsRepository->getEventsList();
    $this->view->assign('eventsList', $events);
}

In View File you can access like this.

<f:for each="{eventsList}" as="events">
    <tr>
        <td> {events.event_id} </td>        
        <td> <f:link.external uri="{events.event_link}" target="_blank">{events.event_link}</f:link.external></td>
        <td><f:format.date format="d-m-Y">{events.event_date}</f:format.date></td>
    </tr>
</f:for>
Ashish Patel
  • 1,011
  • 13
  • 27
0

Have you tried not to use the same varibale name for the iterators in both of your foreach loops?

Daniel
  • 6,916
  • 2
  • 36
  • 47
  • I've tried it now, seems to make no difference. Actually, in the second section, the variable that's passed in, has a different name already (parent-iter vs. iter) – Urs Feb 16 '14 at 09:19