Eduardo Sousa
Eduardo Sousa

Reputation: 1075

Different value_options in Form Collection

I hava a Collection, in which a field User (a multiselect) depends on a previous Select, the Department. Therefore each User select contain a different "value_options".

How can I set different "value_options" when retrieving the form for each row of the Collection?

Upvotes: 0

Views: 80

Answers (1)

Ermenegildo
Ermenegildo

Reputation: 1308

You have different options:

  • You create an API endpoint to retrieve form options
  • You make this into two different pages, the first one you choose the department and the second one you choose the user (ew)
  • You populate the form in server-side and you filter the selects on client side

I personally discourage the second option. Is there just to say that it is a possible solution, but NO.

The first option, the API, is interesting, but requires actually more work, especially if it is the only endpoint in your application.

The third option is the one I always use, since it requires the less code and it quite simple to implement.

In your form, you have your two elements:

$this->add([
    'name' => 'department_id',
    'type' => 'Select',
    'attributes' => [
        'id' => 'department_id'
    ],
    'options' => [
        'value_options' => [
            1 => 'Marketing',
            2 => 'IT',
            3 => 'Logistic'
        ]
    ]
]);

$this->add([
    'name' => 'user_id',
    'type' => 'Select',
    'attributes' => [
        'id' => 'user_id',
        'multiple' => true
    ],
    'options' => [
        'value_options' => [
            [
                'value' => 1,
                'label' => 'John Doe - Marketing',
                'attributes' => ['data-department-id' => 1]
            ],
            [
                'value' => 2,
                'label' => 'Jane Doe - Marketing',
                'attributes' => ['data-department-id' => 1]
            ],
            [
                'value' => 3,
                'label' => 'Jack Doe - IT',
                'attributes' => ['data-department-id' => 2]
            ],
            [
                'value' => 4,
                'label' => 'Dana Doe - IT',
                'attributes' => ['data-department-id' => 2]
            ],
            [
                'value' => 5,
                'label' => 'Frank Doe - Logistic',
                'attributes' => ['data-department-id' => 3]
            ],
            [
                'value' => 6,
                'label' => 'Lara Doe - Logistic',
                'attributes' => ['data-department-id' => 3]
            ]
        ]
    ]
]);

As you can see, all the users are put in the value_options. Keep in mind that this is just an example, you should use custom elements to populate this kind of selects ;)

Then, in your view, you render the elements:

<?= $this->formElement($this->form->get('department_id')); ?>
<?= $this->formElement($this->form->get('user_id')); ?>

And you finally add the JS code to handle the filter. Here I use jQuery, but it's not necessary to use it:

$(function () {
    // Filter users when you load the page
    filterUsers(false);
    // Filter users when you change value on multiselect
    $('#department_id').on('change', function () {
        filterUsers(true);
    });
});
function filterUsers(resetValue) {
    var departmentId = $('#department_id').val();
    // Remove previous value only when filter is changed
    if (resetValue) {
        $('#user_id').val(null);
    }
    // Disable all options
    $('#user_id option').attr('disabled', 'disabled').attr('hidden', true);
    // Enable only those that respect the criteria
    $('#user_id option[data-department-id=' + departmentId + ']').attr('disabled', false).attr('hidden', false);
}

Final tip: don't forget to create and add to the form a Validator to check the couple department_id - user_id is correct, just to avoid (on my example) to accept Lara Doe (logistic) with IT department ;)

Upvotes: 1

Related Questions