Vuejs - Passing attribute name to a Child component - laravel-5

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>

Related

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

Vue.js 3 - Add list items from component dynamically

I am new to vue, I found some examples but I could not reproduce in my situation.
I have some inputs user will fill out and once it clicks the button, the information will populate a list of items. I am trying to crete < li > with a OrderListItem component. But I am getting this error:
runtime-core.esm-bundler.js?5c40:217 Uncaught ReferenceError: machines is not defined
at eval (OrderListItem.vue?fb66:14)
Here is the form
<template>
<div>
<div class="flex flex-col mb-4 md:w-full m-1">
<label for="planter_model_id">Planter</label>
<select v-model="registration.planter_model_id" name="planter_model_id">
<option disabled selected>Planter</option>
<option v-for="planter in planters" :key="planter" :value="planter.id">{{planter.brand.name}} {{planter.name }}</option>
</select>
</div>
<div class="flex flex-col mb-4 md:w-full m-1">
<label class=" for="lines">Lines</label>
<Input v-model="registration.lines" type="number" name="lines" />
</div>
<Button type="button" #click="addItemOrder">Add</Button>
</div>
<div>
<ul>
<OrderListItem :machines="machines" />
</ul>
<div>
</template>
Here is my code
export default {
components: {
OrderListItem,
Button,
},
props: {
planters:{
type:Array,
required: true
},
},
data() {
return {
machines: [], //this what I wish to be passed to OrderListItem component
registration:{
lines:null,
planter_model_id:null,
},
}
},
methods:{
addItemOrder(){
let item = {}
item.planter_model_id = this.registration.planter_model_id
item.lines = this.registration.lines
this.machines.push(item)
}
}
};
And here is my OrderListItem component that I created on another file:
<template>
<li v-for="machine in machines" :key="machine">
<div class="flex-initial w-3/5">
<p>Planter: {{machine.planter_model_id}}</p>
<p>Lines: {{machine.lines}}</p>
</div>
</li>
</template>
<script>
export default {
name: 'OrderListItem',
props:{
machines,
}
}
</script>
I don’t know if it is relevant but I am using vue3 and laravel.
I am very newbie here and from what I learned I think if machines array was a prop I would be able to access it on my component. But I will dynamically add a and remove itens from machines array and I think props receive data from server so It should not be declared there, that why I declared inside data().
Thanks =)
You should define the prop by adding its type and default value :
export default {
name: 'OrderListItem',
props:{
machines:{type:Array,default:()=>[]},
}
}

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.

Vue component select some options by default

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/

Resources