# Problems with dynamic drop-down lists in cakephp 3

**URL:** <https://discourse.cakephp.org/t/problems-with-dynamic-drop-down-lists-in-cakephp-3/7934>\
**Category:** Need Help\
**Created:** [June 11, 2020, 6:24pm UTC](https://discourse.cakephp.org/t/problems-with-dynamic-drop-down-lists-in-cakephp-3/7934 "2020-06-11T18:24:36Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![ecei](https://avatars.discourse-cdn.com/v4/letter/e/f08c70/32.png) [@ecei](https://discourse.cakephp.org/u/ecei)\
**Post date:** [June 11, 2020, 6:24pm UTC](https://discourse.cakephp.org/t/problems-with-dynamic-drop-down-lists-in-cakephp-3/7934/1 "2020-06-11T18:24:36Z")

</div>

Friends, I have 3 tables: products, categories and subcategories. I am trying to register products and through two dependent drop-down lists on the form (categories and subcategories). That is, when selecting the category, the subcategories are loaded in the other list, but I’m having difficulties with that even consulting the documentation! I am grateful if anyone can point a way! I’ll summarize the fields!

Here is my table:

* * *

products: id, name, category\_id, subcategory\_id

categories: id, name

subcategories: id, name, category\_id

* * *

I’m registering the new product like this:

```auto
 public function add()
    {
        $product = $this->Products->newEntity();
        if ($this->request->is('post')) {
            $product = $this->Products->patchEntity($product, $this->request->getData());
            if ($this->Products->save($product)) {
                $this->Flash->success(__('The produto has been saved.'));
                return $this->redirect('/admin/products/');
            }
            $this->Flash->error(__('The produto could not be saved. Please, try again.'));
        }
        $categories = $this->Products->Categories->find('all')->contain(['Subcategories']);    
        $subcategories = $this->Products->Subcategories->find('list', ['limit' => 200]);
        $this->set(compact('product', 'categories', 'subcategories'));
    }

```

ProductTable.php

```auto
.
.
$this->belongsTo('Categories', [
            'foreignKey' => 'category_id',
            'joinType' => 'INNER',
        ]);
        $this->belongsTo('Subcategories', [
            'foreignKey' => 'subcategory_id',
            'joinType' => 'INNER',
        ]);
.
.

```

CategoriesTable.php

```auto
.
$this->hasMany('Product', [
      'foreignKey' => 'category_id',
]);
.

```

SubcategoriesTable.php

```auto
.
 $this->belongsTo('Categories', [
            'foreignKey' => 'category_id',
            'joinType' => 'INNER',
]);
$this->hasMany('Product', [
            'foreignKey' => 'subcategory_id',
]);
.

```

Product =\> add.ctp

```auto
<php
$categories_list = [];
$subcategories_list = [];

foreach($categories as $category){

   $categories_list[$category->id] = $category->name; 

   foreach($category->subcategories as $subcategory){
     $subcategories_list[$category->id][$subcategory->id] = $subcategory->name;
   }
}

?>

<div class="produtos form large-9 medium-8 columns content">
    <?= $this->Form->create($product, ['class' => 'ajax_page']) ?>
    <fieldset>
        <legend><?= __('Add Produto') ?></legend>
        <?php

          echo $this->Form->select('category_id', ['options'=>$categories_list,'id'=>'category']);

         echo $this->Form->select('subcategory_id', ['options'=>[], 'id'=>'subcategory']);
?>
  
  </fieldset>
    <?= $this->Form->button(__('Submit')) ?>
    <?= $this->Form->end() ?>
</div>

```

```auto
<script>

var subCategories = <?= json_encode($subcategories_list); ?>;

$(document).ready(function(){
         $('#category').change(function(){

  var categoryId = $(this).val();

  var subCategoriesObject = subCategories[categoryId];

  $('#subcategory option:gt(0)').remove();
  var subCategoriesSelect = $('#subcategory');

  $.each(subCategoriesObject, function(key,value) {
     subCategoriesSelect.append($("<option></option>").attr("value", key).text(value));
 });

});
});

</script>

```

* * *

With this update, there is no error, but it does not load the name of the subcategories.

Category:[![enter image description here](https://i.stack.imgur.com/q8Jmv.png)](https://i.stack.imgur.com/q8Jmv.png)

Subcategory: [![enter image description here](https://i.stack.imgur.com/TUuYi.png)](https://i.stack.imgur.com/TUuYi.png)

I appreciate any comment or example!

---

<div class="post-metadata">

**Author:** ![dreamingmind](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/dreamingmind/32/1857_2.png) [@dreamingmind](https://discourse.cakephp.org/u/dreamingmind)\
**Post date:** [June 11, 2020, 8:29pm UTC](https://discourse.cakephp.org/t/problems-with-dynamic-drop-down-lists-in-cakephp-3/7934/2 "2020-06-11T20:29:34Z")

</div>

The error seems to be saying the path to the class Router can no be determined.

You probably need a `use` statement on the template file or a fully qualified reference to the class:

recommended

```auto
//add.ctp
use Cake\Routing\Router;

//more code here

```

or something like this

```auto
    ...
    $.ajax({
        dataType:'json',
        type: "POST",
        url: '<?php echo Cake\Routing\Router::url(array("controller" => "Products","prefix" => "admin", "action" => "add")); ?>' ,
        data: dataString,
        ...

```

---

<div class="post-metadata">

**Author:** ![ecei](https://avatars.discourse-cdn.com/v4/letter/e/f08c70/32.png) [@ecei](https://discourse.cakephp.org/u/ecei)\
**Post date:** [June 12, 2020, 1:08am UTC](https://discourse.cakephp.org/t/problems-with-dynamic-drop-down-lists-in-cakephp-3/7934/3 "2020-06-12T01:08:18Z")

</div>

Thank you. The error has been resolved. I made an update, but it does not filter the subcategory from the category. I believe that a detail is missing that I cannot see. Thanks if you can look at the code!

---

<div class="post-metadata">

**Author:** ![dreamingmind](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/dreamingmind/32/1857_2.png) [@dreamingmind](https://discourse.cakephp.org/u/dreamingmind)\
**Post date:** [June 12, 2020, 4:37am UTC](https://discourse.cakephp.org/t/problems-with-dynamic-drop-down-lists-in-cakephp-3/7934/4 "2020-06-12T04:37:11Z")

</div>

Possibly not the whole problem but:

Your two selects are not constructed properly.

You provide one string and one array argument:

```auto
echo $this->Form->select(
   'category', 
   ['options'=>$categories_list,'id'=>'category']
);
echo $this->Form->select(
   'subcategory', 
   ['options'=>$subcategories_list, 'id'=>'subcategory']
);

```

However, you should provide one string and two array arguments like this:

```auto
echo $this->Form->select(
   'category', 
   $categories_list, 
   ['id'=>'category']
);
echo $this->Form->select(
   'subcategory', 
   $subcategories_list, 
   ['id'=>'subcategory']
);

```

The way your code is currently written will prevent the select elements from getting the id attributes you are expecting so the javascript can’t bind the change function.

[https://book.cakephp.org/3/en/views/helpers/form.html#creating-select-pickers](https://book.cakephp.org/3/en/views/helpers/form.html#creating-select-pickers)

---

<div class="post-metadata">

**Author:** ![ecei](https://avatars.discourse-cdn.com/v4/letter/e/f08c70/32.png) [@ecei](https://discourse.cakephp.org/u/ecei)\
**Post date:** [June 12, 2020, 5:06pm UTC](https://discourse.cakephp.org/t/problems-with-dynamic-drop-down-lists-in-cakephp-3/7934/5 "2020-06-12T17:06:35Z")

</div>

I did it the way you mentioned, but it loads all subcategories, regardless of the category you select. I put ‘options’ =\> [], but it also doesn’t load data.

---

<div class="post-metadata">

**Author:** ![dreamingmind](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/dreamingmind/32/1857_2.png) [@dreamingmind](https://discourse.cakephp.org/u/dreamingmind)\
**Post date:** [June 12, 2020, 5:47pm UTC](https://discourse.cakephp.org/t/problems-with-dynamic-drop-down-lists-in-cakephp-3/7934/6 "2020-06-12T17:47:55Z")

</div>

This is the code I put in a template file to test. I don’t have your databases so I hand coded simple arrays when needed. This works form me

```auto
<script>
    $(document).ready(function () {
        var subCategories = {
            '0': [
                'cat0.0', 'cat0.1', 'cat0.2',
            ],
            '1': [
                'cat1.0', 'cat1.1', 'cat1.2',
            ],
            '2': [
                'cat2.0', 'cat2.1', 'cat2.2',
            ],
        };
        $('#category').change(function () {

            var categoryId = $(this).val();
            var subCategoriesObject = subCategories[categoryId];

            $('#subcategory option:gt(0)').remove();
            var subCategoriesSelect = $('#subcategory');

            $.each(subCategoriesObject, function (key, value) {
                subCategoriesSelect.append($("<option></option>").attr("value", key).text(value));
            });

        });
    });

</script>

<?php
echo $this->Form->create();
echo $this->Form->select(
    'category',
    [0 => 'cat0', 1 => 'cat1', 2 => 'cat2'],
    ['id' => 'category']);

echo $this->Form->select(
    'subcategory',
    [],
    ['id' => 'subcategory']
);
echo $this->Form->submit();
echo $this->Form->end();
?>

```

I do get a 1 entry hold-over that can be tweaked out of the code by changing the selects to:

```auto
    'category',
    ['cat0', 'cat1', 'cat2'],
    ['id' => 'category', 'empty' => 'Choose one']);

echo $this->Form->select(
    'subcategory',
    [],
    ['id' => 'subcategory', 'empty' => 'Choose one']
);

```

---

<div class="post-metadata">

**Author:** ![ecei](https://avatars.discourse-cdn.com/v4/letter/e/f08c70/32.png) [@ecei](https://discourse.cakephp.org/u/ecei)\
**Post date:** [June 12, 2020, 6:55pm UTC](https://discourse.cakephp.org/t/problems-with-dynamic-drop-down-lists-in-cakephp-3/7934/7 "2020-06-12T18:55:42Z")

</div>

Likewise, subcategories do not carry values. They only appear in the category.

```auto
<?php
$categories_list = [];
$subcategories_list = [];

foreach($categories as $category){

   $categories_list[$category->id] = $category->name; 

   foreach($category->subcategories as $subcategory){
     $subcategories_list[$category->id][$subcategory->id] = $subcategory->name;
   }
}
?>             

<?= $this->Form->select('category_id', ['cat0', 'cat1', 'cat2'],['id' => 'categories', 'empty' => 'Choose one']);?>

<?= $this->Form->select('subcategory_id',[],['id' => 'subcategories', 'empty' => 'Choose one']);?>

```

* * *

```auto
<script>
    $(document).ready(function () {
        var subCategories = {
            '0': [
                'cat0.0', 'cat0.1', 'cat0.2',
            ],
            '1': [
                'cat1.0', 'cat1.1', 'cat1.2',
            ],
            '2': [
                'cat2.0', 'cat2.1', 'cat2.2',
            ],
        };
        $('#category').change(function () {

            var categoryId = $(this).val();
            var subCategoriesObject = subCategories[categoryId];

            $('#subcategory option:gt(0)').remove();
            var subCategoriesSelect = $('#subcategory');

            $.each(subCategoriesObject, function (key, value) {
                subCategoriesSelect.append($("<option></option>").attr("value", key).text(value));
            });

        });
    });

</script>

```

---

<div class="post-metadata">

**Author:** ![dreamingmind](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/dreamingmind/32/1857_2.png) [@dreamingmind](https://discourse.cakephp.org/u/dreamingmind)\
**Post date:** [June 12, 2020, 7:29pm UTC](https://discourse.cakephp.org/t/problems-with-dynamic-drop-down-lists-in-cakephp-3/7934/8 "2020-06-12T19:29:02Z")

</div>

I don’t understand. Is there a question in your last post?

The code works like this for me:

![Screen Shot 2020-06-12 at 12.20.50 PM](https://canada1.discourse-cdn.com/flex029/uploads/cakephp/original/2X/9/991687de38fd0d7de33b3bcac6cb426cde864031.png) Initial view

![Screen Shot 2020-06-12 at 12.20.58 PM](https://canada1.discourse-cdn.com/flex029/uploads/cakephp/original/2X/5/575be0ce83fd633da399516a2ee864715f1ff9a7.png) Initial values of Categories

![Screen Shot 2020-06-12 at 12.21.14 PM](https://canada1.discourse-cdn.com/flex029/uploads/cakephp/original/2X/8/812e9c5aa042861641e9ca19a1288db696e89a68.png) Initial value of Subcategories

![Screen Shot 2020-06-12 at 12.21.24 PM](https://canada1.discourse-cdn.com/flex029/uploads/cakephp/original/2X/5/572432df6a1ebf9dba10275af3c61d6f13c61663.png) Subcategories after choosing Category 0

![Screen Shot 2020-06-12 at 12.21.36 PM](https://canada1.discourse-cdn.com/flex029/uploads/cakephp/original/2X/f/f6600f06dd2e18eddd30326cad53b832f1ee7195.png) Subcategories after choosing Category 1

---

<div class="post-metadata">

**Author:** ![ecei](https://avatars.discourse-cdn.com/v4/letter/e/f08c70/32.png) [@ecei](https://discourse.cakephp.org/u/ecei)\
**Post date:** [June 12, 2020, 11:10pm UTC](https://discourse.cakephp.org/t/problems-with-dynamic-drop-down-lists-in-cakephp-3/7934/9 "2020-06-12T23:10:48Z")

</div>

It’s very weird. I left the code clean. I removed everything that could be interfering. I believe it is something in js.

```auto
<!DOCTYPE html>
<html>
<body>

<?php
echo $this->Form->create();
echo $this->Form->select('category_id',[0 => 'cat0', 1 => 'cat1', 2 => 'cat2'],['id' => 'category']);

echo $this->Form->select('subcategory_id',[],['id' => 'subcategory']);

echo $this->Form->submit();
echo $this->Form->end();
?>

<script>
  $(document).ready(function () {
    var subCategories = {
      '0': [
      'cat0.0', 'cat0.1', 'cat0.2',
      ],
      '1': [
      'cat1.0', 'cat1.1', 'cat1.2',
      ],
      '2': [
      'cat2.0', 'cat2.1', 'cat2.2',
      ],
    };
    $('#category').change(function () {

      var categoryId = $(this).val();
      var subCategoriesObject = subCategories[categoryId];

      $('#subcategory option:gt(0)').remove();
      var subCategoriesSelect = $('#subcategory');

      $.each(subCategoriesObject, function (key, value) {
        subCategoriesSelect.append($("<option></option>").attr("value", key).text(value));
      });

    });
  });

</script>

</body>
</html>

```

Log JS:

 ![js](https://canada1.discourse-cdn.com/flex029/uploads/cakephp/original/2X/5/5c04ef40507e82046dda14758f94fa1b33e0fa56.png)  
Submenu options simply do not appear. I will review the code more carefully!

---

<div class="post-metadata">

**Author:** ![Zuluru](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/zuluru/32/1230_2.png) [@Zuluru](https://discourse.cakephp.org/u/Zuluru)\
**Post date:** [June 12, 2020, 11:54pm UTC](https://discourse.cakephp.org/t/problems-with-dynamic-drop-down-lists-in-cakephp-3/7934/10 "2020-06-12T23:54:15Z")

</div>

`$ is not defined` generally means you’re trying to use jQuery without actually having loaded jQuery.

---

<div class="post-metadata">

**Author:** ![ecei](https://avatars.discourse-cdn.com/v4/letter/e/f08c70/32.png) [@ecei](https://discourse.cakephp.org/u/ecei)\
**Post date:** [June 13, 2020, 12:40am UTC](https://discourse.cakephp.org/t/problems-with-dynamic-drop-down-lists-in-cakephp-3/7934/11 "2020-06-13T00:40:20Z")

</div>

I loaded jquery.

The error persists in this line:

```auto
.
$(document).ready(function () {
.
.

```

---

<div class="post-metadata">

**Author:** ![ecei](https://avatars.discourse-cdn.com/v4/letter/e/f08c70/32.png) [@ecei](https://discourse.cakephp.org/u/ecei)\
**Post date:** [June 13, 2020, 1:15am UTC](https://discourse.cakephp.org/t/problems-with-dynamic-drop-down-lists-in-cakephp-3/7934/12 "2020-06-13T01:15:30Z")

</div>

Sorted out. It was a jquery import problem. Something basic! I managed to make it work. I’ll try to make the adjustments and load the initial form because the subcategories still don’t appear!
