Vue component select some options by default - laravel

UPDATE: the issues does not reproduce with "CDN" style. Here's the perfectly working JSBin: https://jsbin.com/ziqasifoli/edit?html,js,output
It looks that it is connected to something amongst webpack/gulf/elixir/vuefy.. I.e., all that Laravel 5.3 infrastructure. Not sure even where to start debugging.
...
I'm struggling with a simple (as I thought) component, that gets name, options and selected as input and displays multiple selectbox:
<!-- TagSelector.vue: -->
<template>
<select :name="name" v-model="selected" multiple>
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
</template>
<script>
export default {
props: ['name', 'options', 'selected'],
}
</script>
.
// app.js
Vue.component('tags-selector', require('./components/form_fields/TagsSelector.vue'));
const app = new Vue({
el: '#app'
});
.
<!-- some.form.blade.php -->
<tags-selector
class="form-control"
name="posted_data[tags]"
:selected="['opt1', 'opt2']"
:options='{!! json_encode($options) !!}'
></tags-selector>
It displays selector as expected, but no options pre-selected there.
How do I get it working?

To set some options as selected by default you will want to bind them to data, to do this simply make a copy of your selected prop and use v-model to bind it, which you can do with the created hook:
created: function() {
this.selectedCopy = this.selected;
},
data: function(){
return {
selectedCopy: []
}
}
Then simply bind them by using v-model:
<select :name="name" v-model="selectedCopy" multiple>
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
Here's the JSFiddle: https://jsfiddle.net/3cq1jjL8/

Related

Laravel Livewire and select2 dropdown inside of bootstrap modal

I have a select2 blade component that I'm using inside of a bootstrap modal. Everything is working as expected, except when the modal form is submitted, the styling of the select 2 is lost, and a new empty option (must be the placeholder) is shown as an option, but only in the selects where I'm doing a yes/no option where the value is either 1 or 0 (See code below).
The styling is messed up on all, but the extra placeholder option only shows up on some.
Here's the normal way it should look, and does look when you first open the modal after a page refresh:
After submitting the modal it looks like this (notice the extra placeholder option):
Here's the code for my select2 component:
#props(['id', 'usePlaceholder' => null])
<div wire:ignore style="width:100%;" id="select2-{{ $id }}">
<select {{ $attributes }} id="{{ $id }}" name="{{ $id }}[]" class="form-select select2" data-width="100%" data-select2-id="{{ $id }}">
#if ($usePlaceholder)
<option></option>
#endif
{{ $slot }}
</select>
</div>
{{-- blade-formatter-disable --}}
#push('custom-scripts')
<script>
$(document).ready(function() {
let select2 = $('#' + #js($id));
select2.select2({
dropdownParent: $('#select2-' + #js($id)),
placeholder: 'Select an option',
minimumResultsForSearch: 15
});
***The below listeners I can comment out, they have no effect as far as I can tell, just including them for reference***
window.addEventListener('hideModal', event => {
select2.val(null).trigger('change');
});
window.addEventListener('set'+#js(ucfirst($id)), event => {
select2.val(event.detail).trigger('change');
});
});
</script>
#endpush
{{-- blade-formatter-enable --}}
And here's where I'm actually using the component:
<div class="col-md-6">
<x-input.group label="Sales Tax" for="salesTax" :error="$errors->first('salesTax')">
<x-input.select2 usePlaceholder="{{ empty($salesTax) ? 'true' : '' }}" wire:model.defer="salesTax" id="salesTax">
<option name="no" id="sales-tax-0" value="0">No</option>
<option name="yes" id="sales-tax-1" value="1">Yes</option>
</x-input.select2>
</x-input.group>
</div>
I've tried destroying and re-initializing the select2 when the modal is dismissed, but that hasn't done anything for me.

Laravel Livewire: Bootstrap Select-Picker unable to render

I want to load categories and multiple sub categories according to all the categories that are selected, inside a multi-step form at step 4, but I am not able to select multiple categories using bootstrap selectpicker (multiple selects) library inside livewire component. The issue with using Bootstrap-Select with Livewire is that both of these libraries use JavaScript to update the page dynamically, which is probably causing conflicts. If I try accessing the same without livewire, it works perfectly fine, but with livewire I am unable to render it.
form.blade
#section('content')
<livewire:multi-step-form />
#endsection
#push('before-styles')
<link rel="stylesheet prefetch" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.1/css/bootstrap-select.css" />
#endpush
#push('before-scripts')
<script rel="javascript prefetch" src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.bundle.min.js"></script>
<script rel="javascript prefetch" src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.18/js/bootstrap-select.min.js" integrity="sha512-yDlE7vpGDP7o2eftkCiPZ+yuUyEcaBwoJoIhdXv71KZWugFqEphIS3PU60lEkFaz8RxaVsMpSvQxMBaKVwA5xg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
#endpush
multi-step-form.blade
<select wire:model="categories" name="categories[]" class="selectpicker form-control" multiple data-live-search="true" required id="categories" title="{{ trans('select category') }}">
#foreach($categories as $category)
<option value="{{$category->id}}" {{ (collect(old('categories'))->contains($category->id)) ? 'selected' : '' }}>
{{$category->category}}
</option>
#endforeach
</select>
Some Failed Attempts
Inside livewire component
Attempt 1
<script>
document.addEventListener('livewire:load', function () {
$('.selectpicker').selectpicker();
});
</script>
This works well but only once, i.e. at the start when livewire was loaded. This doesn't work, after the livewire component is updated by some input. So I added a code right below it:
Attempt 2
<script>
document.addEventListener('livewire:load', function () {
$('.selectpicker').selectpicker();
$('.selectpicker').selectpicker('render');
});
</script>
This didn't work too. Some few articles had render separated in updated script so I did that too.
Attempt 3
<script>
document.addEventListener('livewire:load', function () {
$('.selectpicker').selectpicker();
});
document.addEventListener('livewire:updated', function () {
$('.selectpicker').selectpicker('render');
});
</script>
Unfortunately this didn't work either.
I have tried adding the same scripts to my app.js too later, but am not sure where am I going wrong, and how can I make this working.
Attempt 4
Kept the scripts as is, and added wire:ignore in parent div
<div wire:ignore class="form-group">
<select wire:model="categories" name="categories[]" class="selectpicker form-control" multiple data-live-search="true" required id="categories" title="{{ trans('select category') }}">
#foreach($categories as $category)
<option value="{{$category->id}}" {{ (collect(old('categories'))->contains($category->id)) ? 'selected' : '' }}>
{{$category->category}}
</option>
#endforeach
</select>
</div>
As suggested in livewire/livewire/issues/45, but this didn't work as well.

Making Vue Select component reusable (Laravel), returns [object Object]

I'm trying to create a reusable select component - initially, just to prove things were working I loaded the select directly in the vue file - which works with data.
I have the following in php controller:
$countries = Country::pluck('name', 'id');
return Inertia::render('Create', compact('countries'));
In the Create.vue file I tested this code which works:
<select class="form-control" v-model="selCountry">
<option v-for="(country, id) in countries" :key="id" :value="id">
{{ country }}
</option>
</select>
When I tried to make the select component reuseable, I would keep getting [object Object] being returned here is the code:
Select-Component.vue
<template>
<select
class="form-control"
#change="$emit('update:modelValue', $event.target.value)"
ref="select"
>
<option
v-for="(data, key) in options"
:key="key"
:value="key"
:selected="data === modelValue"
>
{{ data }}
</option>
</select>
</template>
<script>
export default {
props: ["modelValue", "options"],
emits: ["update:modelValue"],
methods: {
focus() {
this.$refs.select.focus();
},
},
};
</script>
Btw here is some example data that is being passed from php to vue:
101 => "Germany"
225 => "UK"
Thanks in advance.
and finally loading the component with:
<select id="countries" :options="countries" />
Update: sorry just to add I am trying to achieve this without using any npm packages.
Thanks

Vuejs - Passing attribute name to a Child component

I am trying to create a Vue SelectComponent. One of the attributes I am want to pass to the component is the name of the Select like so:
<select-component selectName="providers"></select-component>
And in my component I have :
<template>
<select :name="{selectName}" >
<option value="bla">{{selectName}}</option>
</select>
</template>
<script>
export default {
props: ['selectName'],
data() {
return {
}
}
}
</script>
<style scoped>
</style>
However, when I look at my chromeDev tools I see it generated:
<select data-v-674655fa="" data-v-70be8f72="" name="[object Object]"><option data-v-674655fa="" value="bla">providers</option></select>
Note: name="[object Object]"
Expected is : name="providers"
I am using Vuejs in a Laravel project.
Many thanks.
<template>
<select :name="selectName" > //without the brackets
<option value="bla">{{selectName}}</option>
</select>
</template>

In Vuejs how do I bind select options to object

I'm trying to use interpolation in a template select options like normal
<select class="form-control" id="staff" name="staff">
<option selected disabled>- Select -</option>
#foreach($staff as $aStaff)
<option value="{{$aStaff->id}}">{{$aStaff->initials}}</option>
#endforeach
</select>
The compile error is clear
Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead.
But i'm still unsure of correct usage. Vue documentation simply gives example
<select v-model="selected">
<!-- inline object literal -->
<option v-bind:value="{ number: 123 }">123</option>
</select>
However i'm unsure how to translate this into using the foreach I need above
Something like this is invalid
<option :value="$aStaff->id">{{$aStaff->initials}}</option>
So just not sure how to interpret ?
Edit: tried using v-for, i get no errors but nothing in the select options
<select class="form-control" id="staff" name="staff">
<option selected disabled>- Select -</option>
<div v-for="aStaff in staff">
<option :value="aStaff.id">aStaff.initials</option>
</div>
</select>
I have staff defined in custom component:
<sale v-if="showModal" #sale="calcFees" :staff="{{$staff}}"></sale>
So when i simply do {{staff}} in the component page, it shows the data i expect to see.
Sale.vue component definition:
<script>
export default {
data: function () {
return {
price: null
}
},
props: {
staff: {
type: Array,
required: true
}
},
methods: {
onSale(){
this.$emit('sale', this.price)
}
}
}
</script>
The code is iterating over a div. Instead, iterate the option.
<option v-for="aStaff in staff" :value="aStaff.id">{{aStaff.initials}}</option>
And remove the div of course.

Resources