Laravel vue-multiselect error - laravel-5

I am trying to implement vue-multiselect (version 1.1.3) with Laravel 5.
In my vue file I have this code:
<template>
<div class="dropdown">
<multiselect
:seleted="multiValue"
:show-labels="false"
:options="options"
:placeholder="placeholder"
:searchable="true"
:allow-empty="false"
:multiple="true"
key="name"
label="name"
#update="updateSelected"
></multiselect>
<label v-show="showLabel" for="multiselect"><span></span>Language</label>
</div>
</template>
<script>
import { Multiselect } from 'vue-multiselect';
export default {
components: { Multiselect },
props: {
selected: null,
options: {
type: Array, default: function () {
return []
}
},
placeholder: 'Select...'
},
methods: {
updateSelected (newSelected) {
this.selected = newSelected
}
}
}
</script>
In my blade file:
<div class="form-group">
<drop-down
:options="{{ $members_list->toJson() }}"
></drop-down>
</div>
In my controller:
$members = DB::table('members')
->orderBy('member_first_name', 'asc')
->get();
$members_list = $members->map(
function($member) {
return [
"value" => $member->member_id,
"label" => $member->member_first_name. " ". $member->member_last_name
];
}
);
When I run the page I get a select list with all the members in it, but when I try to select one, it turns Red, it is added to the selected list on top but I cannot select more options and in firebug I get this error:
[Vue warn]: You are setting a non-existent path "selected" on a vm instance. Consider pre-initializing the property with the "data" option for more reliable reactivity and better performance.
What am I missing?

Typo might be causing issues?
:seleted="multiValue"
Should be :selected="multiValue"
BTW :selected is deprecated in the version 2.0. :value has taken it's place.

I think it is because there is no variable called 'multiValue' in your component.
In :seleted="multiValue" , using the variable "options" instead of "multiValue"

Related

Multiselect vuejs and laravel form

I'm trying to use multiselect into my laravel project.
I'm able to select several option, in my vue pluggin, they are present, but when i submit my form, the value is null. There is something that i miss, but i don't know what ...
Here some of my code :
My Component :
<template>
<div>
<label class="typo__label">Chosir les pays à mettre en avant </label>
<multiselect
v-model="defaultCountry"
:options="options"
placeholder="Pays prioritaires"
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:searchable="true"
name="defaultCountry"
label="name"
track-by="name"
>
</multiselect>
</div>
</template>
<script>
import Multiselect from "vue-multiselect"
export default {
components: {
Multiselect,
},
name: "country-selector",
props: {
countriesList:
{
type: Object,
default: null,
},
},
data() {
return {
options: [],
defaultCountry: [],
}
},
methods: {
fillOptionsWithCountries() {
this.options = Object.entries(this.countriesList).map(
([code, name]) => ({code, name})
)
},
emitCountries(){
}
},
mounted() {
this.fillOptionsWithCountries();
}
}
</script>
<style scoped>
</style>
-My blade part :
<div class="form-group">
<dtc-country-selector
:countries-list="{{ json_encode(__('country')) }}"
>
</dtc-country-selector>
</div>
I tried to add "value" and v-model, but nothing change. I tried to use input hidden with v-model on my defaultCountries, but obviously my v-model isn't defined into blade.

vue3 Cannot read property 'insertBefore' of null

I'm getting this error when i try to update my data fields in vuejs.
data() {
return {
form : useForm({
imageFile : null,
img_id : null,
}),
product_images : this.images,
}
},
here I'm updating the product_images after the success of post request sent by the user.
like this.
this.form.post(url, {
onStart : () => {
Inertia.on('progress', (event) => {
if (event.detail.progress.percentage) {
NProgress.set((event.detail.progress.percentage / 100) * 0.98);
}
});
},
onFinish : () => {
this.product_images = this.images;
},
})
showing the product_images in template be like
<div v-for="image in product_images" class="col-xl-4 col-lg-6 col-12 mb-3" :key="image.id">
<input-image #changeImage="onChangeImage" :id="image.id" :image="image.image" />
</div>
when product_images changes after the post request, product_images not update in DOM but get this error why?
app.js:12889 Uncaught (in promise) TypeError: Cannot read property 'insertBefore' of null
at insert (app.js:12889)
at mountElement (app.js:9604)
at processElement (app.js:9545)
at patch (app.js:9465)
at patchKeyedChildren (app.js:10315)
at patchChildren (app.js:10093)
at processFragment (app.js:9839)
at patch (app.js:9461)
at patchKeyedChildren (app.js:10174)
at patchChildren (app.js:10117)
Unfortunately the vue error message is not very helpful.
In my case, I had some uninitialized data in the html template like this:
<template>
<div>
{{ data.xyz }}
</div>
</template>
Change this to either:
<template v-if="!!data">
<div>
{{ data.xyz }}
</div>
</template>
Or:
<template>
<div>
{{ data?.xyz }}
</div>
</template>
I fixed it by updating my Vue to the latest version (vue#3.2.20).
In my case, was mistakenly calling app.mount('#app') twice.

How to avoid warning "mutating a prop directly" using Vue and Laravel

I am using Laravel 7 and Vue.js 2.
I want to pass an eloquent query result from a controller to a Vue.js component (passing through a View and another component).
This is my controller:
$permissions = Permission::select('id')->get();
return view('admin')->with(['permissions'=>$permissions]);
This is my view:
<div id="app">
<admin-panel :permissions="{{ $permissions }}"></admin-panel>
</div>
This is admin-panel component (passing data through props):
<template>
<div>
<admin-operations></admin-operations>
<hr>
<insert-employee :permissions="permissions"></insert-employee></div>
</template>
This is insert-employee component script:
<script>
export default {
components: {
},
props: ['permissions'],
mounted() {
console.log('Component mounted.');
},
computed:{
},
data: function() {
return {
}
},
methods: {
}
}
</script>
This is the select in insert-employee component:
<select required v-model="permissions" class="form-control" id="permissions">
<option v-for="permission in permissions" :value="permission.id" :key="permission.id">
{{ permission.id }}
</option>
</select>
The results of the query should be visualized in the select options.
However in the select I can visualize correctly the values in the options, but when I select an option the selection doesn't work and in the console appears two times the following warning:
app.js:40160 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "permissions"
found in
---> <InsertEmployee> at resources/js/components/InsertEmployee.vue
<AdminPanel> at resources/js/components/AdminPanel.vue
<Root>
Can help?
Let's try this. I think we're just mixing the values up a bit. I'll try to think of props that are passed in as a read only thing. In this case permissions is an array that holds the id's of each permission.
Next we'll want to use that array to give our user object some values. This way we aren't trying to manipulate values of permissions. That's where Vue was initially getting angry.
<script>
export default {
components: {},
props: {
permissions: {
type: Array,
required: true,
default: () => [],
}
},
mounted() {
console.log('Component mounted.');
},
computed:{},
data: () => ({
user: {
permissionId: "",
}
}),
methods: {},
}
</script>
Then in your component template:
<select required v-model="user.permissionId" class="form-control" id="user-permissionId">
<option v-for="permission in permissions" :value="permission.id" :key="permission.id">
{{ permission.id }}
</option>
</select>

Find a matching value in Vue component

I have passed this collection (postFavourite) to my vue component via props.
[{"id":1,"user_id":1,"post_id":2,"created_at":"2018-07-24 09:11:52","updated_at":"2018-07-24 09:11:52"}]
How do I then check if any instance of user_id in the collection is equal to userId which is the current logged in user (also sent via props).
Tried
let pf = _.find(this.postFavourite, { "user_id": this.userId})
Keep getting undefined as the value of the pf variable even though this.userID is equal to 1.
New to JS and Vue.js so any help would be great.
Here is the vue component code.
<template>
<div>
<i v-show="this.toggle" #click="onClick" style="color: red" class="fas fa-heart"></i>
<i v-show="!(this.toggle)" #click="onClick" style="color: white" class="fas fa-heart"></i>
</div>
</template>
<script>
export default {
data() {
return {
toggle: 0,
}
},
props: ['postData', 'postFavourite', 'userId'],
mounted() {
console.log("Post is :"+ this.postData)
console.log("User id is: "+ this.userId)
console.log("Favourite Object is :" +this.postFavourite);
console.log(this.postFavourite.find(pf => pf.user_id == this.userId));
},
methods: {
onClick() {
console.log(this.postData);
this.toggle = this.toggle ? 0 : 1;
}
}
}
</script>
This is how I passed the props to vue
<div id="app">
<favorite :post-data="'{{ $post->id }}'" :post-favourite="'{{Auth::user()->favourite }}'" :user-id="'{{ $post->user->id }}'"></favorite>
</div>
I gave up on lodash and find and just messed around with the data in the chrome console to work out how to check the value I wanted.
Then I built a loop to check for the value.
If it found it toggle the like heart on of not leave it off.
This will not be the best way to solve this problem but I'm just pleased I got my first real vue component working.
<template>
<div>
<i v-show="this.toggle" #click="onClick" style="color: red" class="fas fa-heart"></i>
<i v-show="!(this.toggle)" #click="onClick" style="color: white" class="fas fa-heart"></i>
</div>
</template>
<script>
export default {
props: ['postData', 'postFavourite', 'userId']
,
data() {
return {
toggle: 0,
favs: [],
id: 0
}
},
mounted () {
var x
for(x=0; x < this.postFavourite.length; x++){
this.favs = this.postFavourite[x];
if(this.favs['post_id'] == this.postData) {
this.toggle = 1
this.id = this.favs['id']
}
}
},
methods: {
onClick() {
console.log(this.postData)
if(this.toggle == 1){
axios.post('favourite/delete', {
postid: this.id
})
.then(response => {})
.catch(e => {
this.errors.push(e)
})
}
else if(this.toggle == 0){
axios.post('favourite', {
user: this.userId,
post: this.postData
})
.then(response => {
this.id = response.data
})
.catch(e => {
this.errors.push(e)
})
}
this.toggle = this.toggle ? 0 : 1;
}
}
}
</script>
Where I pass my props.
<favorite :post-data="'{{ $post->id }}'"
:post-favourite="{{ Auth::user()->favourite }}"
:user-id="'{{ Auth::user()->id }}'"></favorite>
Thanks to all that tried to help me.
From just the code you provided, I see no issue. However lodash is not required for this problem.
Using ES2015 arrow functions
let pf = this.postFavourite.find(item => item.user_id === this.userId);
Will find the correct item in your array
You can read more about this function in the mdn webdocs
You can use find() directly on this.postFavourite like this:
this.postFavourite.find(pf => pf.user_id == this.userId);
Here is another way to do it that might help you as well.
[EDIT]
In order to use find() the variable needs to be an array, this.postFavourite is sent as a string if you didn't use v-bind to pass the prop thats what caused the error.
To pass an array or an object to the component you have to use v-bind to tell Vue that it is a JavaScript expression rather than a string. More informations in the documentation
<custom-component v-bind:post-favourite="[...array]"></custom-component>

Multiselect with Vue and Laravel

I need to implement a multiselect in the view in which I am working, the idea is to have several options selected in the same select. I have tried some components that I found on the web but without good results.
The route and the driver method in Laravel work well.
I have to feed the Multiselect from a method that brings the data
If you can give me a hand it would be great, I leave the code
<template>
<div>
<div class="col-sm-12">
<select class="form-control form-control-line">
<option v-for="coin in coins" :key="coin.id" value="coin.id">
{{ coin.name }}
</option>
</select>
</div>
</template>
<script>
export default {
data () {
coins: [],
},
created() {
this.getCoins();
},
methods: {
getCoins(){
let urlCoin = '/dashboard/coins';
axios.get(urlCoin)
.then((response) => {
this.coins = response.data;
})
.catch((err) => {
})
}
}
My Method in the CoinController
class CoinController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function coinList() {
$coins = Coin::orderBy('rank', 'asc')
->select('id', 'name', 'rank')
->get();
return response()->json($coins);
}
}
the idea is to do this
Multiselect
I used Laravel 5.6 and Vuejs
You can't use basic select tag to show multiple selected value that you get from server.. because it only support to select one option.. if you want to select multiple like your pict, you have to add more library like vue multiselect
<multiselect v-model="value",
:options="coins",
:multiple="true",
:close-on-select="false",
:clear-on-select="false",
:hide-selected="true",
:preserve-search="true",
placeholder="Pick some"
label="name",
track-by="name",
:preselect-first="true" >
<template slot="tag" slot-scope="props">
<span class="custom__tag">
<span>{{ props.option.language }}</span>
<span class="custom__remove"
#click="props.remove(props.option)">
x
</span>
</span>
</template>
</multiselect>
<script>
export default {
data () {
value: [],
coins: [],
},
created() {
this.getCoins();
},
methods: {
getCoins(){
let urlCoin = '/dashboard/coins';
axios.get(urlCoin)
.then((response) => {
this.coins = response.data;
})
.catch((err) => {
})
}
}

Resources