Is it possible to pass Multiple Arrays of Data to a sinlge Template?

SilverStripe 4

Is it possible to pass Multiple Arrays of Data to a sinlge Template?

In Silverstripe 4, I’d like to use two Loops on a single page template. The arrays are created inside of a single function inside my Page Controller.

My idea was to create two ArrayLists, then combine them into a third ArrayList, which I pass to the template.

Using SQLSelect, I have some code that creates an ArrayList of data. $queryArray is an array of key=>value pairs.

$sqlQuery = new SQLSelect();
$sqlQuery->setFrom('Wine');
$sqlQuery->addWhere($queryArray);
$results = $sqlQuery->execute();
$SSArrayList = new ArrayList; //new ArrayList;

foreach($results as $result) {
    $SSArrayList->push(new ArrayData($result));
}

I have some other code that creates another ArrayList from the same $results:

foreach($results as $result) {
  if (!empty($result['BrandName'])) {
      $JSBrandsArray->push(array('Brandname'=>$result['BrandName']));
  }
}

Then, the third ArrayList combines these two arrays:

$mainArray = new ArrayList;
$mainArray->push($SSArrayList);
$mainArray->push($JSBrandsArray);

$mainArray is passed to the template like so:

return $this->customise(array('MainArray'=>$mainArray))->renderWith("Layout/WinesList");

Then, in the WinesList.ss template, I thought I could do something like this:

<% loop $MainArray %>
    <% loop $SSArrayList %>
    // show results from $SSArrayList
    <% end_loop %>

    <% loop $JSBrandsArray %>
    // show results from $JSBrandsArray
    <% end_loop %>
<% end_loop %>

If I var_dump() $mainArray from the page controller, $mainArray seems to have all the data, but I can’t figure out how to properly access the data from the template.

Is this even possible? If so, what am I doing wrong?

Thanks.

You should be able to just push the two lists you have into the template:

return $this->renderWith("Layout/WinesList", array('SSArrayList => $SSArrayList, 'JSBrandsArray' => $JSBrandsArray));

Failing that, if you only want to push one combined list in there, you can just change the scope of your loops with:

<% with $MainArray %>
  <% loop $SSArrayList %>
    ...
  <% end_loop %>
  <% loop $JSBrandsList %>
    ...
  <% end_loop %>
<% end_with %>

All of the above is untested, but the theory should be OK!

@Tim is right, just some little typos there in the first bit of code. To expand, the problem in your original post @mckinselberg is that you’re trying to access those arrays by the names ‘SSArrayList’ and ‘JSBrandArray’, but you didn’t set a key for those items when you pushed them in to your MainArray. You could access them with loop $Me probably. As Tim said though, this would be simpler:

return $this->renderWith(
    "Layout/WinesList",
    array(
        'MainArray' => $mainArray,
        'JSBrandsArray' => $JSBrandsArray
    )
);
<% loop $SSArrayList %>
// show results from $SSArrayList
<% end_loop %>

<% loop $JSBrandsArray %>
// show results from $JSBrandsArray
<% end_loop %>

This was my final code. I realized my question wasn’t completely clear. But the help is very appreciated, and was integral. This is what I ended up with. Hopefully my solution illustrates the whole concept.

$mainArray = new ArrayList;
$mainArray->push(new ArrayData($SS_WinesArray));
$mainArray->push(new ArrayData($JS_CountriesArray));
$mainArray->push(new ArrayData($JS_BrandsArray));
// add more as needed

return $this->renderWith("Layout/WinesList",
array(
'SS_WinesArray' => $SS_WinesArray,
'JS_CountriesArray' => $JS_CountriesArray,
'JS_BrandsArray' 	=> $JS_BrandsArray,
// More arrays here, too
)
);

<% loop $SS_WinesArray %>
    // I do JS stuff with this, which interacts with the categories 
    //I have set up in the other arrays,  but prefixed it SS to 
    //differentiate it from the other arrays, which I'm using as category filters
    //I'm trying to (kind of) emulate a relational database with JS.
    // I'm sure there is a better way to do it.
<% end_loop %>

<% loop $JS_CountriesArray %>
// do JS stuff with the just the $JS_CountriesArray
<% end_loop %>

<% loop $JS_BrandsArray %>
// do JS stuff with the just the $JS_BrandsArray
<% end_loop %>

// do JS stuff with more category arrays.

:slight_smile: :wine_glass:

Why do you need the $mainArray ? If you’re pushing the individual data into the template, it would appear to be redundant (and just using memory / cycles for no reason)

@Tim, you are right. The “why” is simply a case of confusion, on my part. After learning that I could ‘send’ multiple arrays to the template with the ‘renderWith’ method, I failed to notice that I no longer needed that $mainArray, and consequently, failed to remove it from my code.

Perhaps, subconsciously, I was too attached to the original idea. Or hadn’t had enough coffee. Or too much.
:slight_smile: :coffee:

1 Like

@Tim For my own understanding, why the ArrayData wrappers if not using any of the functionality it provides?