pass certain value dynamically to computed function in Vue.js - laravel

Im trying to pass an id with the v-model so i can pass that to my computed function. The purpose of my function is to dynamically filter a table without hardcoding the names in the function. The function has to be able to filter both select boxes.
my data is called guides, it has an title/active/language_id/group.
this is my html dropdown:
<select v-model="filterResult" :id="language.id" class="select2-selection custom-select">
<option value="">All</option>
<option v-for="language in languages" v-bind:key="language.id" v-bind:value="language.id">{{ language.name }}</option>
</select>
<select v-model="filterResult" :id="active" class="select2-selection custom-select">
<option value="">All</option>
<option :value=1>Active</option>
<option :value=2>Archived</option>
</select>
Here is my computed function now, but as u can see the "language.id" is hard coded in but i want the function to read it out of <select>. what i tried is putting it in the :id="" but i have no idea to forward it to the function besides the v-model. Purpose of all this is so i can reuse the component without changing anything. So it has to be applied to both select boxes or even more in the future.
filterCertainValue: function (evt) {
if (!this.filterResult) return this.guides;
return this.guides.filter(guide => {
if (guide.language.id == this.filterResult) {
return guide.language.id;
}
})
},

You could create a dynamic filter key that changes based on the last selected <select>:
Create a data property (named "filterKey"):
export default {
data() {
return {
filterKey: null
}
}
}
Add a change-event handler to each <select> to set filterKey to the desired key to use in the computed prop's filtering (e.g., language_id or active):
<select #change="filterKey = 'language_id'">
<!-- language_id options -->
</select>
<select #change="filterKey = 'active'">
<!-- active options -->
</select>
Update the computed prop's filter to use the filterKey:
computed: {
filterCertainValue() {
if (!this.filterResult) return this.guides
👇
return this.guides.filter(guide => guide[this.filterKey] === this.filterResult)
}
},
demo

Related

Redering out a view based on dropdown value in Laravel 7

I would like to render a different view for 4 dropdown values in the controller. I'm new to PHP and Laravel and just starting to understand it.
dropdown html:
<div class="col-md-6">
<select name="employees" class="form-control #error('employees') is-invalid #enderror">
<option value="">-- {{ __('choose') }} --</option>
<option value="micro">1 - 5</option>
<option value="small">5 - 50</option>
<option value="medium">50 - 500</option>
<option value="large">500 +</option>
</select>
Controller:
class RegisterControllerStep2 extends Controller
{
public function form()
{
return view('auth.register_step2');
}
public function saveData(Request $request)
{
auth()->user()->update($request->only(['company_name', 'website', 'employees']));
return redirect()->route('home');
}
}
I want to redirect the user to another page other than home based on their selection from the employees dropdown above.
You need something like this
public function saveData(Request $request)
{
auth()->user()->update($request->only(['company_name', 'website', 'employees']));
if($request->employees==='micro'){
return redirect()->route('micro');
}
return redirect()->route('home');
}
Another thought I had on this is you could also do something like
return redirect()->route($request->employees);
As long as you had all your routes set up correctly with matching names to the values in your employees select
For giving a better experience I add this jquery function to justrusty's answer.
By doing this, it is not required for the user to press submit button for changes being applied.
Add a form with an id on the select:
<form action="something" method="post">
#csrf
<select id="employees" name="employees" class="form-control #error('employees') is-invalid #enderror">
<option value="">-- {{ __('choose') }} --</option>
<option value="micro">1 - 5</option>
<option value="small">5 - 50</option>
<option value="medium">50 - 500</option>
<option value="large">500 +</option>
</select>
</form>
Then add below jquery to the end of body section:
$('#employees').change(function() {
this.form.submit();
});
And at last, as justrusty said, redirect to the desired page in the controller:
if($request->employees==='micro'){
return redirect()->route('micro');
}

How to retrieve selected option value?

Hi guys new to laravel here! i am using selected option drop down list The First Select contains the countries and the second one has the states, now When i try to store the in database i am not getting the proper selected state instead i am always getting the first state in the second select Option!! i am using query Builder.
This is How i am retrieving Countries and states
public function store(Request $request)
{
$country = DB::table("countries")->where("id",$request->daira);
$state = DB::table("states")->where("country_id",$request->daira);
$daira = $country->get()->first()->name;
$impact = $state->get()->first()->commune;
dd($impact);
}
Note: dd($impact); Should be retrieving the selected state, instead it's retrieving the first value on the Selection List
So my Question is How do i get it to retrieve The proper Selected state !? Hope my question is clear Thanks in Advance.
Updated:
In the First Select option I have Countries name and in the second option i have
states each country has maximum 3 states, let's say Country A has 3 States A1,A2 and A3 And i want to select State A2 from the select option Value and instead of getting A1 by default like my case in the Question
Updated: I Am using VueJs
This is The form code
<template>
<div class="modal-body">
<div class="form-group">
<select name="direction" class="form-control">
<option value="">Selctionner Direction</option>
<option value="ENERGIE">ENERGIE</option>
<option value="HYDRAULIQUE">HYDRAULIQUE</option>
<option value="ENVIRONNEMENT"> ENVIRONNEMENT</option>
<option value="AMENAGEMENT">AMENAGEMENT</option>
<option value="P.T.T">P.T.T</option>
<option value="TOURISME">TOURISME</option>
<option value="TRANSPORT">TRANSPORT</option>
<option value="TRAVAUX PUBLICS">TRAVAUX PUBLICS</option>
<option value="EDUCATION">EDUCATION</option>
<option value="ENSEIGNEMENT SUPERIEUR">ENSEIGNEMENT SUPERIEUR</option>
<option value="URBANISME">URBANISME</option>
<option value="FORMATION PROFESSIONNELLE">FORMATION PROFESSIONNELLE</option>
<option value="SANTE">SANTE</option>
<option value="JEUNESSE-SPORTS CULTURE">JEUNESSE-SPORTS CULTURE</option>
<option value="PROTECTION SOCIALE">PROTECTION SOCIALE</option>
<option value="INFRASTRUCTURES ADMINISTRATIVES">INFRASTRUCTURES ADMINISTRATIVES</option>
<option value="HABITAT">HABITAT</option>
<option value="COMMERCE">COMMERCE</option>
<option value="LOGEMENT">LOGEMENT</option>
<option value="LOCAUX A USAGE PROFESSIONNELE">LOCAUX A USAGE PROFESSIONNELE</option>
<option value="FORET">FORET</option>
</select>
</div>
<div class="form-group">
<label>Selctionner Daira:</label>
<select name="daira" class='form-control' v-model='country' #change='getStates()'>
<option value='0' >Select Country</option>
<option v-for='data in countries' :value='data.id'>{{ data.name }}</option>
</select>
</div>
<div class="form-group">
<label>Selctionner Commune:</label>
<select name="impact" class='form-control' v-model='state'>
<option value='0' >Select State</option>
<option v-for='data in states' :value='data.id'>{{ data.commune }}</option>
</select>
</div>
<div class="form-group">
<label >Intitule :</label>
<input type="text" class="form-control" name="intitule" required>
</div>
</div>
</template>
And this is My Script
<script>
export default {
mounted() {
console.log('Component mounted.')
},
data(){
return {
country: 0,
countries: [],
state: 0,
states: []
}
},
methods:{
getCountries: function(){
axios.get('/api/getCountries')
.then(function (response) {
this.countries = response.data;
}.bind(this));
},
getStates: function() {
axios.get('/api/getStates',{
params: {
country_id: this.country
}
}).then(function(response){
this.states = response.data;
}.bind(this));
}
},
created: function(){
this.getCountries()
}
}
</script>
can you post the result of dd($request->all()) ?
assuming your select name is daira and impact, you should be able to get the posted value with this:
public function store(Request $request)
{
$daira = $request->daira;
$impact = $request->impact;
}
I understand your issue first state returns because of when you passed country id it returns all the state related this country.
So that you need to pass state Id from state drop-down.
<select name="impact">
<option value="id">{{ STATE NAME }} </option>
</select>
And then you need to pass that state id in controller.
$state = DB::table("states")->where("id",$request->impact);
Hope you understand your queries
I assume $request->daira is country ID
public function store(Request $request)
{
//here you selected a country with provided country ID
//this returns Query Builder object
$country = DB::table("countries")->where("id",$request->daira);
//here you are returning all the states where the country_id is
//the provided country ID
//Note that this returns all the states (Query Builder object)
$state = DB::table("states")->where("country_id",$request->daira);
//You return `Illuminate\Support\Collection` then you got the first item
//from collection
$daira = $country->get()->first()->name;
//You returned all the states `Illuminate\Support\Collection`
//and you picked the first state from the collection,
//which is likely the first item in your
//form select field options
$impact = $state->get()->first()->commune;
dd($impact);
}
Because you didn't specify state_id, you will always get lists of all the states under the given country.
I assume table relationship is Country -> hasMany -> State
You need to add state_id as constraint, so only one state is picked
$state_id = $request->state
I assume you have state in your form
$state = DB::table("states")
->where("country_id",$request->daira)
->where('id', $state_id)
->first();
$impact = $state->commune

Laravel Ajax dropdown example

can someone please share working example of laravel ajax dropdown. there are so many examples about dependable dropdown, but i want simple dropdown of only one column, i have two tables teacher and nation, when teacher profile is open i want dropdown of nationality using ajax.
i have done it without ajax, but i don't know how to do with ajax.
without ajax:
<select name="nation_id" class="custom-select" >
<option selected value=" ">Choose...</option>
#foreach($nations as $nations)
<option value="{{#$nation_id}}" {{#$teacher->nation_id== $nations->id ? 'selected' : ''}} >{{#$nations->nation}}</option>
#endforeach
Controller:
$nations = nation::all();
<select class="form-control" name="nation_id" id="nation_id">
<option value="">Select nation</option>
#foreach($nations as $nation)
<option value="{{ $nation->nation_id }}">{{ $nation->nation_name }} </option>
#endforeach
</select>
<select class="form-control" name="teacher" id="teacher">
</select>
now the ajax code:
<script type="text/javascript">
$('#nation_id).change(function(){
var nid = $(this).val();
if(nid){
$.ajax({
type:"get",
url:"{{url('/getTeacher)}}/"+nid,
success:function(res)
{
if(res)
{
$("#teacher").empty();
$("#state").append('<option>Select Teacher</option>');
$.each(res,function(key,value){
$("#teacher").append('<option value="'+key+'">'+value+'</option>');
});
}
}
});
}
});
</script>
now in controller file;
public function getTeacher($id)
{
$states = DB::table("teachers")
->where("nation_id",$id)
->pluck("teacher_name","teacher_id");
return response()->json($teachers);
}
And last for route file:
Route::get('/getTeacher/{id}','TeachersController#getTeacher');
Hope this will work..
Good Luck...
Create a route for your method which will fetch all the nations-
Route::get('nations-list', 'YourController#method');
Create a method in your controller for the above route-
public function method()
{
$nations = Nation::all()->pluck('nation', 'id');
return response()->json($nations)
}
Add a select box like this in your HTML-
<select id="nation_id" name="nation_id"></select>
If you want to auto select the option based on a variable then you can do this-
<input type="hidden" name="teacher_nation_id" id="teacher_nation_id" value="{{ $teacher->nation_id ?? '' }}">
And then add this script in your HTML to fetch the nation list on page load-
<script>
$(document).ready(function($){
$.get('nations-list', function(data) {
let teacher_nation_id = $('#teacher_nation_id').val();
let nations = $('#nation_id');
nations.empty();
$.each(data, function(key, value) {
nations.append("<option value='"+ key +"'>" + value + "</option>");
});
nations.val(teacher_nation_id); // This will select the default value
});
});
</script>

Laravel 5.2 Vue.js computed doesn't work

How can I show objects returned by vue?
The provinces are Ok, But cities v-for doesn't work.
This is My Blade :
<select v-model="ProvinceModel" name="province" id="province" class="border-radius-0 form-control padding-y-0">
<option v-for="province in provinces" value="#{{ province.id }}"> #{{ province.name }} </option>
</select>
<select name="city" id="city" class="border-radius-0 form-control padding-y-0">
<option v-for="city in cities" value="#{{ city.id }}"> #{{ city.name }} </option>
</select>
This is my scripts
new Vue({
el: '#vue',
methods: {
fetchProvinces: function () {
this.$http.get('{{url('api/provinces')}}').then(function (provinces) {
this.$set('provinces', provinces.data)
});
}
},
computed: {
cities() {
this.$http.get("{{url('api/cities')}}/" + this.ProvinceModel).then(function (cities) {
console.log(cities.data);
this.$set('cities', cities.data)
});
}
},
ready: function () {
this.fetchProvinces()
},
});
And route
Route::get('cities/{provinces_id}', function ($id = 8) {
return \App\province::find($id)->cities()->get();
})->where('id', '[0-9]+');
Computed functions should return something, and sycnchronously. You're not returning anything.
You're also attempting to set this.cities as data, but this.cities is already a computed function. One's gonna override the other and cause inconsistent/confusing behavior.
Fetching cities asynchronously should be a method, just like your fetchProvinces method. You should fetch them when ProvinceModel is changed, which you can probably do via a #change event on the selector, or a Vue watcher on the value of ProvinceModel.
Side note: Generally, it's best to define your data items in the component's data parameter. If you check your JS console, Vue's likely throwing warnings about that.
Vuejs not flexible, you can get value through jquery, pass it to control. Element by ref method is good.
Vuejs can not wait for worker,when it get busy, so naturally variable when it is not in value show undefined.

Laravel Select2 old input after validation

I'm using Select2 in my webapplication. I load my Select2 boxes with Ajax. When validation fails, all the inputs are filled as before except the Select2 box. How can I restore the old value after the form validation fails? My bet was using Request::old('x'), but this inserts the value (in my case an user ID) instead of the selected text. So for example the text John would become 27 in the selectbox. How can I get the text back?
<select id="customer" name="customer" class="searchselect searchselectstyle">
</select>
The js:
token = '{{csrf_token()}}';
$(".searchselect").select2({
ajax: {
dataType: "json",
type: "POST",
data: function (params) {
return {
term: params.term,
'_token': token,
'data' : function(){
var result = [];
var i = 1;
$('.searchselect').each(function(){
result[i] = $(this).val();
i++;
});
return result;
}
};
},
url: function() {
var type = $(this).attr('id');
return '/get' + type;
},
cache: false,
processResults: function (data) {
return {
results: data
};
}
}
});
Edit
The only (dirty) solution I found so far is the following:
<select id="customer" name="customer" class="searchselect searchselectstyle">
#if(Request::old('customer') != NULL)
<option value="{{Request::old('customer')}}">{{$customers->where('id', intval(Request::old('customer')))->first()->name}}</option>
#endif
</select>
$customers is a list of all customers, so this means that for each Select2 box I need to query a big list of items in order to make it work. This will be pretty inefficient if we're talking about thousands of rows per Select2 box.
I guess there must be a better solution. Who can help me?
Normally to programmatically set the value of a select2, you would expect to use the .val() method followed by a .trigger('change') call as per their documentation (and other queries like this on SO). However, select2 themselves have something in their documentation about preselecting options for remotely sourced data.
Essentially their suggestion boils down to (after initalizing your AJAX-driven <select>):
make another AJAX call to a new API endpoint using the pre-selected ID
dynamically create a new option and append to the underlying <select> from a promise function (.then()) after the AJAX call is finished
could also use some of the regular jQuery callback chaining functions for this
trigger a change event
trigger a select2:select event (and pass along the whole data object)
Assuming you're already flashing the old data to the session, Laravel provides handy access to the previously requested input in a variety of ways, notably these three:
static access via the Request class e.g. Request::old('customer') as in the OP
the global old() helper e.g. old('customer'), which returns null if no old input for the given field exists, and can have a default as a second parameter
using the old() method on the Request instance from the controller e.g. $request->old('customer')
The global helper method is more commonly suggested for use inside Blade templates as in some of the other answers here, and is useful when you don't need to manipulate the value and can just plug it straight back in, which you would with things like text inputs.
The last method probably provides you with the answer you're looking for - instead of querying the entire collection from inside of the view, you're able to either manipulate the collection from the controller (similar to the OP, but should be nicer since it's not parsing it in the view) or make another query from the controller based on the old ID and fetch the data you want without having to trawl the collection (less overhead):
$old_customer = Customer::find($request->old('customer'));
Either way, you'd have the specific data available at your fingertips (as a view variable) before the blade template processes anything.
However you choose to inject the data, it would still follow the pattern suggested by select2:
get the pre-selected data
create an option for it
trigger the appropriate events
The only difference being you don't need to fetch the data from another API endpoint (unless you want/need to for other programmatic reasons).
I end up using similar flow like your. But my blade template is using htmlcollection package.
Controller:-
Let's say you are in create() method. When validation failed, it will redirect back to the create page. From this page, you can repopulate the list.
$customer_list = [];
if(old('customer') != NULL){
$customer_list = [old('customer') => $customers->where('id', old('customer'))->first()->name];
}
Blade View:
{{ Form::select('customer', $customer_list, null, ['class' => 'searchselect searchselectstyle', 'id' => 'customer']) }}
I did it with an input hidden for the text and it works well:
This form is showed in a Popup and ajax (using Jquery-UJS)
Form:
<form action="{{ route('store_item', $order) }}" method="POST" data-remote="true">
{{ csrf_field() }}
<div class="form-group{{ $errors->has('item_id') ? ' has-error' : '' }}">
<label class="control-label col-sm-2" for="item_id">Item: </label>
<div class="col-sm-10">
<select name="item_id" class="form-control" id="item_id">
#if(old('item_id') != null)
<option value="{{ old('item_id') }}" selected="selected">
{{ old('item_title') }}
</option>
#endif
</select>
</div>
{!! $errors->first('item_id', '<p class="text-center text-danger"<strong>:message</strong></p>') !!}
</div>
<input type="hidden" id="item_title" name ="item_title" value="{{ old('item_title') }}" />
<div class="form-group{{ $errors->has('quantity') ? ' has-error' : '' }}">
<label class="control-label col-sm-2" for="quantity">Cantidad: </label>
<div class="col-sm-10">
<input name="quantity" type="number" class="form-control" id="quantity" value="{{ old('quantity') }}"/>
</div>
{!! $errors->first('quantity', '<p class="text-center text-danger"><strong>:message</strong></p>') !!}
</div>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancelar</button>
<button type="submit" class="btn btn-primary" data-disable-with="Guardando...">Guardar</button>
</form>
JAVASCRIPT:
<script type="text/javascript">
$(document).ready(function(){
$('#item_id').select2({
placeholder: 'Elige un item',
ajax: {
url: '{{ route('select_item_data') }}',
dataType: 'json',
delay: 250,
processResults: function (data) {
return {
results: $.map(data, function (item) {
return {
text: item.title,
id: item.id
}
})
};
},
cache: true
}
});
$('#item_id').on('change', function(e){
var title = $(this).select2('data')[0].text;
$('#item_title').val(title);
});
});
</script>
VALIDATION IN STORE METHOD (CONTROLLER):
$validator = Validator::make($request->all(), [
'item_id' => 'required',
'quantity' => 'required'
]);
if ($validator->fails()) {
return redirect()
->route('create_item', $order)
->withInput($request->all())
->withErrors($validator);
}
It's very important to send 'withInput' and 'withErrors' in the redirection, because we are working with a popup and ajax that is created again and doesn't keep the old values.
Maybe you can try (once the ajax call has ended) :
var oldCustomer = $('#customer > option[value={{ Request::old('customer') }}]');
if (oldCustomer.length > 0) {
oldCustomer.attr('selected', 'selected');
}
Same problem; I'm using a similar solution: If the old $id is set, I get the name and I use it as a variable for the view; Note that I also forward the id because I also used this method to pre-fill the form (coming from another place), but in this case, the name only should have been used, and for the id {{ old('author_id') }} can be used in the view:
In the controller:
elseif (($request->old('author_id') !== null) && ($request->old('author_id') != '')) {
$my_author_id = $request->old('author_id');
$my_name = Author::find($my_author_id)->name;
return view('admin/url_author.create', compact('my_name', 'my_author_id'));
}
And in the view (more precisely, in a partial used for creation & edition):
#if (isset($record)) // for use in edit case with laravelcollective)
<select class="form-control js-data-author-ajax" id="author_id" name="author_id">
<option value="{{ $record->author_id }}">{{ $record->author->name }}</option>
</select>
#else
#if (isset($my_name)) // old input after validation + pre-filling cases
<select class="form-control js-data-author-ajax" id="author_id" name="author_id">
<option value="{{ $my_author_id }}">{{ $my_name }}</option>
</select>
#else // for create cases
<select class="form-control js-data-auteur-ajax" id="auteur_id" name="auteur_id">
<option></option>
</select>
#endif
#endif
Your code is bit confusing. I don't understand why you are using a POST request to get data using ajax to fill a select2 box.
Assuming the data returned using ajax call is in the below format.
[
{
"id": "Some id",
"text": "Some text"
},
{
"id": "ID 2",
"text": "Text 2"
},
]
Now what you can do is pass in an extra parameter to your ajax call as below
url: function() {
var type = $(this).attr('id');
#if(old('customer'))
return '/get' + type + '?customer='+ {{ old('customer') }};
#else
return '/get' + type;
#endif
}
Now in your controller while returning data you can throw an extra attribute selected:true for an ID matching that particular ID.
if( Request::has('customer') && Request::input('customer') == $id )
{
[
"id" => $id,
"text" => $text,
"selected" => "true"
]
}
else
{
[
"id" => $id,
"text" => $text,
]
}
If I understood you right I can recommend you to have for each your select2 box hidden input <input type="hidden" name="customer_name" value="{{old('customer_name', '')}}"> where after change event for select2 you can insert selected name (etc. John). So if validation is fails you have:
<select id="customer" name="customer" class="searchselect searchselectstyle">
#if(!is_null(old('customer')))
<option value="{{old('customer')}}">{{old('customer_name')}}
</option>
#endif
</select>
I think your own solution is pretty much correct. You say the list of $customers will get pretty big.
$customers->where('id', intval(Request::old('customer')))->first()
Do you need to have the list stored in a variable $customers? You could just search the id you want
App\Customer::where('id', intval(Request::old('customer')))->first()
Searching by id should not be inefficient. Otherwise you could send the name with the form and store it in the old request. Shown below with some (dirty) javascript.
$("#form").submit( function() {
var sel = document.getElementById("customer");
var text= sel.options[sel.selectedIndex].text;
$('<input />').attr('type', 'hidden')
.attr('name', "selected_customer_name")
.attr('value', text)
.appendTo('#form');
return true;
});
Then like yrv 16s answer:
<option value="{{old('customer')}}">{{old('selected_customer_name')}}
You could do something like this:
First in controller pass tags to view using pluck helper like below:
public function create()
{
$tags= Customer::pluck('name','name');
return view('view',compact('tags'));
}
Then in your form try this:
{!! Form::select('tag_list[]',$tags,old('tag_list'),'multiple','id'=>'tag_list']) !!}
Don't forget to call the select2 function.
$('#tag_list').select2();
And finally in controller:
public function store(ArticleRequest $request)
{
$model = new Model;
$tags=$request->input('tag_list');
$model->tag($tags);
}
Notice tag function is not a helper in Laravel, You implement it! The function takes names and attaches them to the instance of some thing.
Good Luck.

Resources