ArrayData ArrayList Nested loops

Silverstripe Version: 4.1

No surprises… I’m new to SS and it’s template lang.

I have a nested multi dim arrays that I need to modify and output. I have tried using an ArrayList of ArrayData’s but found I couldn’t modify a value nor output the values. I got further with the output than I did using native arrays. I at least got the first label out but couldn’t iterate the values key.

In normal PHP it’s:

# Static atm, eventually pulled from somewhere

			$all_filters = [
				[
					'label' => "SOME FILTER",
					'filter' => 'category',
					'values' => [
						'Durapipe' =>
						[
							'checked' => ''
						],
						'Nupi' =>
						[
							'checked' => ''
						],
						'UPP' =>
						[
							'checked' => ''
						],
						'Sumps' =>
						[
							'checked' => ''
						],
						'Valves and Fittings' =>
						[
							'checked' => ''
						]
					]
				],
				[
					'label' => 'ANOTHER FILTER',
					'filter' => 'sub_category',
					'values' => [
						'Smartflex' =>
						[
							'checked' => '',
						],
						'Smart Conduit' =>
						[
							'checked' => '',
						]
					]
				],
			];

# If the filter is active, set it as so for render
			foreach ($all_filters as $key => $filters)
			{
				if ($value = $request->getVar($filters['filter']))
				{
					$values = explode(',', $value);

					foreach ($values as $value)
					{
						$all_filters[$key]['values'][$value]['checked'] = 'checked';
					}
				}
			}

(excuse the formatting… this forum really gives me the sh!ts!)

So that structure works as I’d hoped… but I can’t seem to output it. This get’s me basically nothing. Just one checkbox with a title of 1.

<% loop $all_filters %>
	<div class="filter-title">$label</div>
	<% loop $values %>
		<div class="filter-container">
			<input id="todo" type="checkbox" name="$label" class="filter" value="$label" $checked/>
			<label for="todo">$label</label>
		</div>
	<% end_loop %>
<% end_loop %> 

Appreciate any help :slight_smile:

Well I kept hacking and I don’t know if I made i better or worse…

I kept the native arrays like above but added horrific hack in at the end to convert the hot mess to ArrayList/ArrayData:


$hack = ArrayList::create();

foreach ($all_filters as $filter)
{
    # Create an ArrayData out of the values array
	$values = ArrayData::create($filter['values']);

    # Overwrite the values array with this ArrayData    
	$filter['values'] = $values;

    # Wrap all of it in an ArrayData
	$list_hack = ArrayData::create($filter);

    # Push it all onto an ArrayList
	$hack->push($list_hack);
}

So that’s all sorts of ugly but it’s an ArrayList of ArrayData and I still can’t render it with the code above.

did you fix it? Keen for the solution…

Wow this is an old one… The project this was for has been dead for some time. I dusted off version control for it and it looks like it did work with this;

Created an array structure:

array (
  'Cars' => 
  array (
    'Title' => 'Cars',
    'ParsedTitle' => 'cars',
    'Facets' => 
    array (
      12 => 
      array (
        'Title' => 'Audi',
        'ParsedTitle' => 'audi',
        'ProductCount' => 0,
        'Checked' => '',
      ),
      2 => 
      array (
        'Title' => 'Ferarri',
        'ParsedTitle' => 'ferarri',
        'ProductCount' => 2,
        'Checked' => '',
      ),
   ),
  'Colours' => 
   array (
   'Title' => 'Colours',
    'ParsedTitle' => 'colours',
    'Facets' => 
    array (
      5 => 
      array (
        'Title' => 'Black',
        'ParsedTitle' => 'black',
        'ProductCount' => 2,
        'Checked' => '',
      ),
      9 => 
      array (
        'Title' => 'Green',
        'ParsedTitle' => 'green',
        'ProductCount' => 2,
        'Checked' => '',
      ),
   )
)

You may not need to do the above. I was doing operations on the array.
To get it into something parseable for the view template syntax I looped over it and created ArrayData items that were pushed onto an ArrayList

$FacetGroups = new ArrayList();

foreach ($data as $FacetGroup)
{
   $Facets = new ArrayList();

   foreach ($FacetGroup['Facets'] as $FacetID => $Facet)
   {
      # Create ArrayData out of the inner most arrays 
      $Facets->push(
	     new ArrayData([
            'Title' => $Facet['Title'],
            'ParsedTitle' => $Facet['ParsedTitle'],
            'ProductCount' => $Facet['ProductCount']
		])
      );
   }
   
   # Create ArrayData outer array including it's ArrayList of Facet ArrayData's
   $FacetGroups->push(
      new ArrayData([
         'Title' => $FacetGroup['Title'],
         'ParsedTitle' => $FacetGroup['ParsedTitle'],
         'Facets' => $Facets
      ])
);

End of that you have an ArrayList with ArrayData and nested ArrayLists with ArrayDatas.

The template code to output it:

<% loop $FacetGroups %>
   <div class="facet-title">$Title</div>

   <% loop $Facets %>
      <div class="facet-container">
         <input id="{$Up.ParsedTitle}_{$ParsedTitle}" type="checkbox" name="$Up.ParsedTitle" class="facet" value="$ParsedTitle" <% if $Checked == 'true' %> checked="checked" <% end_if %>/>
         <label for="{$Up.ParsedTitle}_{$ParsedTitle}">$Title ($ProductCount)</label>
     </div>
    <% end_loop %>
<% end_loop %>

Result:

1 Like