How to show items in dropdown by cascading in laravel 5.6?
How to show items in dropdown by cascading in laravel 5.6?
I have 3 tables i.e. menu, submenu and page.
Menu Table
Schema::create('menu', function (Blueprint $table)
$table->increments('parent_id')->primary();
$table->string('name');
$table->timestamps();
);
Submenu Table
Schema::create('submenu', function (Blueprint $table)
$table->increments('submenu_id')->primary();
$table->integer('parent_id');
$table->foreign('parent_id')
->references('id')
->on('menu')
->onDelete('cascade');
$table->string('title');
$table->timestamps();
);
Page Table
Schema::create('page', function (Blueprint $table)
$table->increments('page_id');
$table->integer('menu_id');
$table->integer('submenu_id');
$table->text('description');
$table->integer('status')->default('1');
$table->softDeletes();
$table->timestamps();
);
addpage.blade.php
<div class="control-group">
<label class="control-label">Menu Name</label>
<div class="controls">
<?php $menu = DB::table('menu')->where('status',1)->get(); ?>
<select name="parent_id" id="parent_id">
<option selected disabled>Select Menu Name</option>
@foreach($menu as $data)
<?php if($data->deleted_at==null) ?>
<option value=" $data->parent_id "> strtoupper($data->name) </option>
<?php ?>
@endforeach
</select>
</div>
</div>
<div class="control-group">
<label class="control-label">Submenu Title</label>
<div class="controls">
<?php //$menu = DB::table('submenu')->where('deleted_at',null)->where('status',1)->get(); ?>
<select name="submenu_id" id="submenu_id">
<option selected disabled>Select Submenu Title</option>
<!-- @foreach($menu as $test)
<?php// $submenu = DB::table('submenu')->where('deleted_at',null)->where('status',1)->where('parent_id',$test->parent_id)->get(); ?>
<?php// print_r($submenu);die; ?>
@endforeach *-->
<?php $submenu = DB::table('submenu')->where('status',1)->get(); ?>
@foreach($submenu as $data)
<?php if($data->deleted_at==null) ?>
<option value=" $data->submenu_id "> $data->title </option>
<?php ?>
@endforeach
</select>
</div>
</div>
How cascade value in dropdown in laravel 5.6?
When i add new page, i want to show submenu according to menu in dropdown...
So, I want to have solution of this...
parent_id
menu
submenu_id
submenu
id
ok, you can take your time..
– Crazy Programmer
Sep 16 '18 at 7:39
Can I just check - is Page only going to display a single sub-menu or list of submenus associated with the given menu?
– Sebastian Sulinski
Sep 16 '18 at 7:46
a menu can have no any submenu or single submenu or multiple submenu ..a menu can display list of submenus
– Crazy Programmer
Sep 16 '18 at 7:50
Will Page record only be valid if it has both - menu and sub-menu?
– Sebastian Sulinski
Sep 16 '18 at 7:51
2 Answers
2
The best way is to use the eager loading. Create a relation with both the models and get the value by using this model query.
$menus= Menu::with('submenu')->get();
<select name="parent_id" id="parent_id">
<option selected disabled>Select Menu Name</option>
@foreach($menu as $key=>$value)
<option value=" $key "> strtoupper($value) </option>
@foreach($key->submenu as $subkey=>$subValue) { ?>
<option value=" $subkey->parent_id "> strtoupper($subValue->name) </option>
@endforeach
@endforeach
</select>
how can i show in addpage.blade.php
– Crazy Programmer
Sep 16 '18 at 10:26
Here's what I've come up with. I've amended migrations a bit:
Schema::create('menus', function (Blueprint $table)
$table->increments('id');
$table->tinyInteger('status')->default(1);
$table->string('name');
$table->timestamps();
);
Schema::create('sub_menus', function (Blueprint $table)
$table->increments('id');
$table->tinyInteger('status')->default(1);
$table->unsignedInteger('menu_id');
$table->string('title');
$table->timestamps();
$table->foreign('menu_id')
->references('id')
->on('menus')
->onDelete('cascade');
);
Schema::create('pages', function (Blueprint $table)
$table->increments('id');
$table->integer('menu_id');
$table->integer('submenu_id');
$table->integer('status')->default(1);
$table->text('description');
$table->softDeletes();
$table->timestamps();
);
Then from within controller
$menus = Menu::where('status', 1)->orderBy('name')->get()->map(function(Menu $menu)
return [
'name' => $menu->name,
'value' => $menu->id,
];
);
$subMenus = SubMenu::where('status', 1)->orderBy('title')->get()->map(function(SubMenu $subMenu)
return [
'name' => $subMenu->title,
'value' => $subMenu->id,
'menu_id' => $subMenu->menu_id,
];
)->groupBy('menu_id');
return view('menu.index')
->with('menus', $menus)
->with('subMenus', $subMenus);
You can see that I've grouped sub-menus using menu_id field, which will represent index of each collection of sub-menus - this way we can then easily replace them in the view.
menu_id
I've added 2 simple VueJs components
VueJs
Form.vue
<script>
export default
props:
inputs:
type: Object,
required: true,
,
data()
return
fields: this.inputs
,
</script>
DependableMenu.vue
<template>
<div>
<slot :options="options"></slot>
</div>
</template>
<script>
export default
props:
parentValue:
type: [Number, String],
default: null,
,
records:
type: [Object, Array],
default: () => ,
,
data()
return
options:
,
mounted()
this.filterRecords(this.parentValue);
,
methods:
filterRecords(parent_id)
if (!parent_id)
this.options = ;
this.options = this.records[parent_id]
,
watch:
parentValue(parent_id)
this.filterRecords(parent_id);
</script>
Registered them within the resources/assets/js/app.js
resources/assets/js/app.js
Vue.component('form-wrapper', require('./components/Form'));
Vue.component('dependable-menu', require('./components/DependableMenu'));
And finally menu/index.blade.php view with the form
menu/index.blade.php
<form-wrapper :inputs=" menu_id: '', submenu_id: '' " inline-template>
<form action="/" method="post">
csrf_field()
<select name="menu_id" v-model="fields.menu_id">
<option value="">Select menu</option>
@foreach($menus as $menu)
<option value=" $menu['value'] "> $menu['name'] </option>
@endforeach
</select>
<dependable-menu :parent-value="fields.menu_id" :records=" $subMenus ">
<div slot-scope="props">
<select name="submenu_id">
<option value="">Select sub-menu</option>
<option v-for="option in props.options" :key="option.value" :value="option.value" v-text="option.name"></option>
</select>
</div>
</dependable-menu>
<button type="submit">SUBMIT</button>
</form>
</form-wrapper>
Tested locally - all works, but give it a try your end and see how it goes.
Did you try it?
– Sebastian Sulinski
Sep 17 '18 at 9:37
i didn't understood the vue.js
– Crazy Programmer
Sep 17 '18 at 10:12
How are you planning on replacing records in the menu after first selection - page reload?
– Sebastian Sulinski
Sep 17 '18 at 11:08
can we use ajax?
– Crazy Programmer
Sep 18 '18 at 8:50
You can use ajax to fetch data for each menu after selection, but you need some sort of javascript to actually make that ajax call - whether it is using vanilla js or some library such as jQuery, Vue etc.
– Sebastian Sulinski
Sep 18 '18 at 10:06
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy
Any particular reason why you have primary key as
parent_idundermenuand thensubmenu_idundersubmenu? Also - really not a good idea to fetch records from within the view. I'll try to help, but you have to give me some time to re-create it locally - I will however use justidcolumns for primary - unless you confirm there was a particular reason for this naming.– Sebastian Sulinski
Sep 16 '18 at 7:30