phpcakephpform-helperscakephp-4.x

CakePHP - Hotw to Generate Select Field with Mutiple Attribute using FormHelper


I need to find a way to set the default values of a select-type field which has the multiple attribute.

Here is the data sent to the view through the controller:

$categories = [
    ['id' => 1, 'description' => 'Hardware'],
    ['id' => 2, 'description' => 'Sofware'],
    ['id' => 3, 'description' => 'Peopleware'],
    ['id' => 4, 'description' => 'Alienware'],
];
$selectedCategoriesIds = [1, 3];
$this->set(compact('categories', 'selectedCategoriesIds'));

And the view looks like this:

<select name="categories[_ids][]" multiple="multiple">
    <?php foreach ($categories as $category): ?>
    <option value="<?= $category->id ?>"<?= (in_array($category->id, $selectedCategoriesIds) ? 'selected' : '') ?>><?= $category->description ?></option>
    <?php endforeach; ?>
</select>

This is the HTML generated in the view:

    <select name="categories[_ids][]" multiple="multiple">
        <option value="1" selected>Hardware</option>
        <option value="2">Software</option>
        <option value="3" selected>Peopleware</option>
        <option value="4">Alienware</option>
    </select>

Everything works perfectly, my question is whether I can get this same result using CakePHP's FormHelper so I don't need to iterate over $categories and make a call to in_array() inside the view. I already consulted the Cookbook but I didn't find anything, or didn't understand how to do it in this specific case. I assume it would be something like:

<?= $this->Form->control('categories._ids', ['some params']) ?>

Thank you.


Solution

  • You should be able to use the form class if your $categories array is structured a little differently. The Cookbook has an example here:

    // HTML <option> elements with values 1 and 3 will be rendered preselected
    echo $this->Form->select(
        'rooms',
        [1, 2, 3, 4, 5],
        [
            'multiple' => true,
            'value' => [1, 3]
        ]
    );
    

    First, just map $categories to a simpler mapped list of the Category id's => descriptions.

    If this category list was data from a database, just select it with 'list' instead of the default method, ex:

    $categories = $CategoriesTable->find('list');
    

    But, if it's not from a Query result, you can still manually convert your array:

    $categories = [
        ['id' => 1, 'description' => 'Hardware'],
        ['id' => 2, 'description' => 'Sofware'],
        ['id' => 3, 'description' => 'Peopleware'],
        ['id' => 4, 'description' => 'Alienware'],
    ];
    
    $formattedCategories = [];
    foreach($categories as $row){
        $formattedCategories[$row['id']] = $row['description'];
    }
    $categories = $formattedCategories;
    

    Once in this format, the regular Form->select will work:

    echo $this->Form->select(
        'categories[_ids][]',
        $categories,
        [
            'multiple' => true,
            'value' => $selectedCategoriesIds
        ]
    );