Laravel dynamic dropdown not being empty - php

My goal is to achieve an dynamic dropdown that will display the value of the second dropdown base on the first dropdown.
A service has many categories and a category belongs to a service so the second dropdown is the category and the first dropdown is the service. When the service is selected it will show all the category based on the service selected.
Here is the code in RequestController.php
public function create()
{
$client = Client::all()->sortBy('client_name', SORT_NATURAL | SORT_FLAG_CASE)->pluck('client_name', 'id');
$services = Service::with('categories')->get()->sortBy('code', SORT_NATURAL | SORT_FLAG_CASE)->pluck('description', 'id');
$categories = Categories::with('service')->get()->sortBy('name', SORT_NATURAL | SORT_FLAG_CASE)->pluck('name', 'id');
return view('encoder-dashboard.analysis-request.create', compact('client', 'services', 'categories'));
}
in my fields.blade.php
<!-- Service Id Field -->
<div class="form-group col-sm-6">
{!! Form::label('service_id', 'Service:') !!}
{!! Form::select('service_id', $services, null, ['class' => 'form-control','required'])!!}
</div>
<!-- Categories Id Field -->
<div class="form-group col-sm-6">
{!! Form::label('category_id', 'Category:') !!}
{!! Form::select('category_id', $categories, null, ['class' => 'form-control','required'])!!}
</div>
The script for handling the request
<script>
$(function() {
$('select[name=service_id]').change(function() {
var url = '{{ url('service') }}' + $(this).val() + '/categories/';
$.get(url, function(data) {
var select = $('form select[name= category_id]');
select.empty();
$.each(data,function(key, value) {
select.append('<option value=' + value.id + '>' + value.name + '</option>');
});
});
});
});
</script>
The route web.php
Route::get('service/{service}/categories', 'ServiceController#getCategories');
And in the ServiceController.php
public function getCategories($service)
{
$service = Service::findOrFail($service);
return $service->categories->pluck(['id','name']);
}
I achieved to get all the data using the pluck. But it empty's the form for the category with the name of category_id
So I guess my problem is within the script or nah?
Appreciate if someone could help.
Thanks in advance.

Try this, I have something similar and there are some small differences.
<script>
JQuery(function() {
$('#service_id').change(function() {
var url = '{{ url('service') }}' + $(this).val() + '/categories/';
$.get(url, function(data) {
var select = $('form select[name= category_id]');
select.empty();
$.each(data,function(key, value) {
select.append('<option value=' + key + '>' + value + '</option>');
});
});
});
});
</script>
Reverse id and name. First the value is selected, the key is optional (your id). See also Laravel Collections pluck
Edit: pluck does not hold an array.
public function getCategories($service)
{
$service = Service::findOrFail($service);
return $service->categories->pluck('name', 'id');
}

,I'm not totally sure what the issue is, but it sounds like it is correctly clearing the data from the select, but not putting it back?
Could be a problem with appending to a changed element, or not properly finding the selector, or maybe it's not dynamic and losing its hook after changing on.('change') vs .change()... (or several things).
Here is a function I use to repopulate. I add the html in the loop and then change the entire select in one go using the hook to $(this) and then trigger the change.
Perhaps this might help you:
// After filtering (any select box across the program), repopulate it -- same function for anything
function ajaxFilterSuccess(typeClass, newArray){
$('.'+typeClass).each(function(i, obj) {
// Only add Please Select to single selects (not multiple / select2) since multis are usually
// many to many pivots without a way to mutate the input away from '' (needs to be null or stopped totally)
if(typeof this.attributes['multiple'] == 'undefined')
var list = '<option value="">Please Select</option>';
if ($(this).val() != null) {
$(this).children(':selected').each(function() {
// Use native JS to get 'this', so it doesn't confuse with the $(this) selector looping
list += '<option value="'+this.value+'" selected>'+this.text+'</option>';
});
}
$(this).empty();
$.each(newArray, function(value,key) {
list += "<option value='" +value + "'>" + key + "</option>";
});
$(this).html(list);
$(this).trigger('change');
});
}

Related

Laravel 5.6: Get selected value from a dropdown to use it in another

6, I'm using a dropdown to read a column from a database table. All I want is to get the selected value on that dropdown and use it to create a new query that will be populated in a new drop-down.
After reading and see several examples I see people using ajax and other people using laravel HTTP request like $request->get() so i don't know which way to take since I'm not familiar with any of those and even when trying several times can't get it to work.
Can anyone give me an insight into the best/efficient way to do it? Is it possible to do it only using php or some feature in laravel that I'm missing?
Here is my controller:
public function selectsector() //this is the dropdown #1 that works fine
{
$sectors = DB::table('Sectors')->whereBetween('SectorID', [1, 10])->value('SectorID');
return view('besttradesview', ['sectors10' => $sectors]);
}
public function selectsubsector() //dropdown #2 not working
{
$subsectors = DB::table('Sectors')->where('parentid', $sectors)->get();
//this line is not working it does not recognize $sector variable
return view('besttradesview', ['subsectors42' => $subsectors]);
}
View with dropdow #1: sector and #2: subsector
<form method="GET">
<div class="selectsector">
<Select class="selectsector" name = "sector">
#foreach($sectors10 as $sector)
<option>{{ $sector->SectorName }}</option>
#endforeach
</select>
<Select class="selectsubsector" name = "subsector">
#foreach($subsectors42 as $subsector)
<option>{{ $subsector->SectorName }}</option>
#endforeach
</select>
</form>
Routes:
Route::get('kitysoftware/besttrades', 'SectorsController#selectsector');
Route::get('kitysoftware/besttrades', 'SectorsController#selectsubsector');
Getting error: Undefined variable: sectors
Ok, i managed to do it using javascript and ajax function with json datatype. I'm new at JavaScript and it took me a while so i'm taking the time to publish the details for the newcomers. Here we go:
The View file:
The trick is to use a html hidden object that captures a route + prefix like in this line before the dropdowns:
<input type="hidden" name="application_url" id="application_url" value="{{URL::to(Request::route()->getPrefix()) }}"/>
The name of this object is "application_url" which we'll be using later in the javascript code to complete the url that the routes needs.
DropDown#1 with name "sectorSelect":
<label class="selectsector">Sector:</label>
<Select class="selectsector" id="sectorSelect" name="sectorSelect" >
<option value=""> -- Please select sector --</option>
#foreach ($sectors10 as $sector)
<option value="{{ $sector->SectorID }}">{{ $sector->SectorName }}</option>
#endforeach
</select>
DropDown #2 with name: "SubsectorSelect"
<label class="selectsector">SubSector:</label>
<Select class="selectsector" id="subSectorSelect" name="subSectorSelect">
<option value=""> -- Select an option --</option> // you don't have to do nothing here since this will be populated it from a query depending on the dropdown#1 selected value
</select>
Now in the web.php routes file:
Route::get('kitysoftware/sectors/subsectors/{id}', 'SectorsController#selectsubsector');
We are creating a route with an {id} parameter. This will be the selected value in dropdown #1. Then we call the "selectsubsector" method in the Sectorscontroller.
Controller:
First dropdown query:
public function selectsector()
{
$sectors = DB::table('Sectors')->select('SectorName', 'SectorID')-
>whereBetween('SectorID', [1, 10])->get();
return view('besttradesview', ['sectors10' => $sectors]);
Second Dropdown query (selectsubsector method):
public function selectsubsector($sectorId)
{
$subsectors = DB::table('Sectors')->select('SectorName', 'SectorID')->where('parentid', $sectorId)->get();
return response()->json($subsectors); //this line it's important since we are sending a json data variable that we are gonna use again in the last part of the view.
}
Final part of the view file The javaScript + ajax function
<script type="text/javascript">
$('#sectorSelect').change(function () { //we watch and execute the next lines when any value from the dropdown#1 is selected
var id = $(this).val(); //we get the selected value on dropdown#1 and store it on id variable
var url = $('#application_url').val(); //we get the url from our hidden element that we used in first line of our view file, and store it on url variable
//here comes the ajax function part
$.ajax({
url: url + "/kitysoftware/sectors/subsectors/" + id, //we use the same url we used in our route file and we are adding the id variable which have the selected value in dropdown#1
dataType: "json", //we specify that we are going to use json type of data. That's where we sent our query result (from our controller)
success: function (data) { //*on my understanding using json datatype means that the variable "data" gets the value and that's why we use it to tell what to do since here.*
//and this final part is where we use the dropdown#1 value and we set the values for the dropdown#2 just adding the variables that we got from our query (in controllert) through "data" variable.
$('#subSectorSelect').empty();
$.each(data, function (key, value) {
$('#subSectorSelect').append('<option value="' + key.SectorID + '">' + value.SectorName + '</option>');
});
}
});
});
</script>
Hope it helps the solution and the explanations. I'm happy to get some feedback as well.
I hope it is your requirement:
<Select class="selectsector" onChange="getSelectorValue( this, '#selector2' )" id="selector1" name="sector">
#foreach($sectors10 as $sector)
<option>{{ $sector->SectorName }}</option>
#endforeach
</select>
<Select class="selectsubsector" onChange="getSelectorValue( this, '#selector1' )" name = "subsector" id="selector2" >
#foreach($sectors10 as $sector)
<option>{{ $sector->SectorName }}</option>
#endforeach
</select>
Add Script to make it work:
<script type="text/javascript">
function getSelectorValue( selectorObj, selector ){
document.querySelector( selector ).value = selectorObj.value;
}
</script>
Controller
public function selectsector()
{
$sectors = Sector::get();
return view('besttradesview', compact('sectors'));
}
public function selectsubsector($sectors)
{
$subsectors = Sectors::where('parentid', $sectors)->get();
if (empty($subsectors)) {
$html = '';
$html = '<option value="">There has no Value</option>';
} else {
$html = '';
foreach ($subsectors as $subsector) {
$html .= '<option value="'.$subsector->id.'">'.$subsector->subsector.'</option>';
}
}
return response()->json(['html' => $html]);
}
route
Route::get('/get-selector/{id}', 'Inventory\selectorController#selectsubsector')->name('get.selector');
ajax
$(document).on('change','.selectsector',function () {
var id= $(this).val();
var url = "{{ URL::to('/get-selector') }}"+ '/' + id;
$.ajax({
url: url,
type: 'get',
dataType:'JSON',
success: function (response) {
console.log(response);
if(response.html==''){
$('.selectsubsector').html('<option value="">There has no Value</option>');
}else{
$('.selectsubsector').html(response.html);
}
},error: function (exception) {
console.log(exception);
}
});
});

Getting data from database using vuejs and laravel

I have a select element and based on the the selection, data is to be retrieved based on the id selected.
blade template
<div id="pers_obj" class="form-group form-duration-div">
{{Form::label("personal_objective", "Personal Objective/KPA")}}
<select name="personal_objective" id="personal_objective" v-model="personal_objective">
<option value="0" class="form-control">--Select Objective--</option>
#foreach($personal_objectives as $personal_objective)
<option value="{{ $personal_objective->id }}" class="form-control">{{ $personal_objective->name}}</option>
#endforeach
</select>
<div v-cloak>#{{personal_objective}}</div>
</div>`
measure.js
var pers_objective = new Vue({
el: '#pers_obj',
data:{
personal_objective: null
},
});
How can I:
retrieve data from database using vuejs
display data from the database using vue js
Looks like you are mixing a bit the PHP and JavaScript code trying some luck. The best way is creating a service response to get the personal objectives like an API.
So lets supose that you create a controller, called at /personal-objectives for example, that returns an array of objects with the structure of { id: number, name: string }
Then your code for the HTML would look like:
<div id="pers_obj" class="form-group form-duration-div">
<select name="personal_objective" v-model="personal_objective">
<option value="0" class="form-control">--Select Objective--</option>
<option v-for="po in pos" value="#{{ po.id }}" class="form-control">#{{ po.name }}</option>
</select>
</div>
And your JavaScript (assuming you are ussing vue-resource library for ajax calls) like:
var pers_objective = new Vue({
el: '#pers_obj',
data: function() {
return {
personal_objective: null,
pos: [];
};
}
created: function() {
this.loadPersonalObjectives();
}
methods: {
loadPersonalObjectives: function() {
this.$http.get('personal-objectives').then((response) => {
this.pos = response.data.pos;
}, (response) => {
console.log(response);
});
}
}
});
The above code will make an ajax GET call when the component is created to /personal-objectives which will return a JSON (don't forget to return the array encoded this way and set the proper header) array of bjects that on error will be displayed in console, and on succed the array will be assigned to the pos javascript variable and updated in the HTML creating the corresponding options reactively!
You may need to update the URL adding the root / in case you are not configuring the vue-resource with the root option (Vue.http.options.root)

laravel 5.2 dynamic dropdown list

I have an event and i want to add artists to it from artists table.
I want to do so by using a dropdown list where it need to get populated by artists name and their is a small '+' next to it to add other artists. Upon doing that a 3rd transitive table where event id and artist id should be inserted as foreign keys.
When I create the event
In my view:
<div class="form-group">
<label for="task-artist" class="col-sm-3 control-label">Artist:</label>
<div class="col-sm-6">
<select name="artist" id="artist" class="form-control input-sm">
<option value=""></option>
#foreach($artists as $artist)
{{$artist->stage_name}}
#endforeach
</select>
</div>
</div>
my controller:
public function index(Request $request)
{
return view('tasks.index', [
'tasks' => $this->tasks->forUser($request->user()),
'artists' => DB::table('artists')->pluck('stage_name', 'id'),
]);
}
public function show($id)
{
//Get results by targeting id
$task = Task::find($id);
//$artist = Artist::lists('stage_name', 'id');
//$artist = Artist::where('active', true)->orderBy('stage_name')->pluck('stage_name', 'id');
//
return view('tasks.show')->with('task',$task);
}
How shall i proceed ?
Please help.
Javascript is your friend here.
Let me write some steps that you can follow to achieve what you are looking for :
1) Have the Div tag and
2) use $.get() function in javascript to get the dynamic values from a controller.
3) $.each() to loop through the data and show it in select input field
4) on either selecting the value or clicking + button that you mentioned do another Javascript call to add the artist to the event.
Example :
HTML
<div class="uk-margin-bottom">
<div id="your select dropdown"></div>
</div>
JAVASCRIPT
$("#artist").change(function() {
getArtists();
});
function getArtist() {
var artist= $('#your div id');
artist.empty();
var code = '';
$.get("/url/" + variable_id, function(data) {
artist.empty();
console.log(data);// once you create route and controller you should see your artists lists here
code += '<label for="event_id" class="uk-form-label">Select Artist</label><select class="uk-width-1-1" name="artist_name" id="artist_name" value="select">';
code += '<option value="">Select Artists</option>';
$.each(data.artist, function(index, value) {
code += '<option value="' + value.artist_name+ '">' + value.artist_name + '</option>';
});
code += '</select>
artist.append(code);
});
}
have a form and add javascript to post artist to the controller and store data into events table. Try and see if you can achieve and follow my steps.

Populate dropdown based on another dropdown selected value in laravel - edit form

I found how to accomplish this on another site and I got it working. My issue is though that I need to use it in my edit form (preferably in the same form as my create form, since my create and edit views use the same form). When I go to my edit page, the "Section" dropdown value is selected as it should be. But the "Subsection" is not, because ofcourse I did not click it. Probably it's a fix too easy for me to see, but I am not quite good with javascript. I basically need the second dropdown (the subsection one) to show the correct options based on which "section" (first dropdown) is selected, on my edit view.
Section Model:
public function subsections()
{
return $this->hasMany('App\Subsection');
}
Subsection Model:
public function section()
{
return $this->belongsTo('App\Section');
}
View:
{!! Form::select('section_id', [null=>'-- Select Section --'] + $sections, null, array('id' => 'section')) !!}
<select id="subsection" name="subsection_id" class="select">
<option>-- First Select Section --</option>
</select>
From my controller: $sections = Section::lists('section', 'id');
Script:
<script>
$(document).ready(function($){
$('#section').change(function(){
$.get("{{ url('api/dropdown')}}",
{ option: $(this).val() },
function(data) {
$('#subsection').empty();
$.each(data, function(key, element) {
$('#subsection').append("<option value='" + key +"'>" + element + "</option>");
});
});
});
});
</script>
Route:
Route::get('api/dropdown', function(){
$id = Input::get('option');
$subsections = Section::find($id)->subsections;
return $subsections->lists('subsection', 'id');
});
If you just want to select the first option in jquery , you can add :
$('#subsection option:eq(1)').prop('selected', true);
Or else if you want to select a particular value, you can do that by
$('#subsection option[value="value_to_be_selected"]').prop('selected', true);
Use this after you have appended all the values to the subsection
In my controller I added:
$subsections = Subsection::where('section_id', '=', $transaction->section_id)->orderBy('subsection', 'asc')->lists('subsection', 'id');
And in my view I did this:
#if(isset($transaction))
{!! Form::select('subsection_id', [null=>'-- Select Subsection --'] + $subsections, null, array('class' => 'select', 'id' => 'subsection')) !!}
#else
<select id="subsection" name="subsection_id" class="select">
<option>-- First Select Section --</option>
</select>
#endif
Problem solved :)
So, what we will do is initially we will send value to the dependent drop-down as "<option value="">Select Something</option>"
and when returning on error create complete drop-down with selected as below value and return, this will reduce lots of javascript calls.
Controller:
if($error){
//create get array of second drop-down, suppose $second_drop
// create complete second drop-down like
$selectbox="";
foreach($second_drop as $option){
$selectbox.="<option value='". $option->id."'";
if($request->option2==$ $option->id){
$selectbox.=" selected ";
}
$selectbox.=">".$option->value."</option>";
}
}
return view('routename', ['selectbox2' => $selectbox]);
View:
<select id="subsection" name="subsection_id" class="select">
{!! $selectbox !!}
</select>

Only allow a certain amount of checked boxes in Laravel

I have a list of ten simple check boxes that all look something like this:
{{ Form::label('waterBox', 'Water:') }}
{{ Form::checkbox('waterBox', 'yes'); }}
{{ Form::label('calBox', 'Calories (kcal):') }}
{{ Form::checkbox('calBox', 'yes'); }}
I don't want the user to be allowed to check more than 5 boxes before submitting the form. How can I make it so that after a sixth box is checked one of the others is unchecked?
Randomly unchecking other checkboxes is a little confusing to your users.
How about disabling the other checkboxes instead?
var $checkboxes = $('input[type=checkbox]');
$checkboxes.change(function () {
if (this.checked) {
if ($checkboxes.filter(':checked').length == 5) {
$checkboxes.not(':checked').prop('disabled', true);
}
} else {
$checkboxes.prop('disabled', false);
}
});
Here's the fiddle: http://jsfiddle.net/F57s9/1/
P.S. If you're not using jQuery, just let me know and I'll whip you up a native solution.
You could call a javascript function (I'm using jQuery in this example) that looks at all the waterBox checkboxes and limits it to 5, something like this:
function limitCheckboxes()
{
var checkedBoxCount = $('[name=waterBox]:checked').length;
$('[name=waterBox]:checked').each(function () {
if ((checkedBoxCount > 5) &&
(this.checked))
{
this.checked = false;
checkedBoxCount--;
}
});
}
Then be sure to name your checkboxes with brackets:
{{ Form::checkbox('waterBox', 'yes', false, ['onclick' => 'limitCheckboxes()']); }}
I haven't tested this, but the general principle should work.
Update: fixed missing ID attribute on checkbox.
Update 2: fixed jQuery selection of checkboxes and counts.
Update 3: fiddle around and got a working example going. The code above should now reflect that. :) Added fiddle code: http://jsfiddle.net/Miggl/XKB7b/

Categories