Same vue code from html not working in blade file - vue.js

below is the code from html:
<div id="app">
<select #change="onSelectUserType()" v-model="type">
<option value="">Who are you?</option>
<option value="tailor">Tailor</option>
<option value="store">Store</option>
<option value="customer">Customer</option>
</select>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script>
new Vue({
el: "#app",
data: {
type: ''
},
methods: {
onSelectUserType: function () {
console.log(this.type)
alert(this.type)
}
},
mounted() {
console.log('mounted');
}
});
</script>
this is code from html that is working, when i apply it inside blade it is not working! it should show alert and console on changing the options, but nothing is visible, also no error is detected what is the issue?

Related

VUE, Can't use selected option value in a select component

Im trying to use a selected option value. Can't show the value or save it.
This is my child component
`
<script>
export default {
props: {
options : {
type:Array,
},
selectOpt:undefined,
}
emits : ['input','change','option:selected']
}
</script>
<template>
<div>
<h1>
Hi, I'm a component
</h1>
<select
v-model="selectOpt"
#change="$emit('input', event.target.value)">
<option v-for="option in options"
:key="option"
>{{option}}</option>
</select>
</div>
</template>
`
This is my parent
`
<script >
import Comp from './Comp.vue'
export default {
data() {
return {
options : [1,2,3,4,5,6],
optSelected : undefined,
}
},
components: {
Comp
}
}
</script>
<template>
<Comp v-model="optSelected" :options="options"></Comp>
<p>
--->{{optSelected}}
</p>
</template>
`
I tried changin the 'input' event and 'change' event. not sure what im doing wrong.
i've found a solution that requires a vue-select library that i prefer not to use.
It's a simple detail: in vue 3, you need to use update:modelValue in order to change the v-model in parent component. (Reference: https://v3-migration.vuejs.org/breaking-changes/v-model.html)
And another thing: you souldn't use the prop as a v-model to prevent side effects in your application. You can read more about it here: https://eslint.vuejs.org/rules/no-mutating-props.html
Hope it helps:
<script>
export default {
props: {
options: {
type: Array
},
modelValue: undefined
},
emits: ['update:modelValue'],
watch: {
innerValue(newValue) {
this.$emit('update:modelValue', newValue)
},
modelValue(newValue) {
this.innerValue = newValue;
}
},
data() {
return {
innerValue: this.modelValue
};
}
};
</script>
<template>
<div>
<h1>Hi, I'm a component</h1>
<select v-model="innerValue">
<option v-for="option in options" :key="option">
{{ option }}
</option>
</select>
</div>
</template>
[Edit] Using Fallthrough Attribute:
You can use the v-bind="$atrrs":
<script>
export default {
props: {
options: {
type: Array
},
},
};
</script>
<template>
<div>
<h1>Hi, I'm a component</h1>
<select v-bind="$attrs">
<option v-for="option in options" :key="option">
{{ option }}
</option>
</select>
</div>
</template>
Read more: https://vuejs.org/guide/components/attrs.html#attribute-inheritance-on-multiple-root-nodes

How can I access the bound value of a <select>'s currently selected <option>?

Say I am making a simple component which wraps a <select>. This component supports v-model, as documented here.
Vue.component('custom-select', {
template: '#component',
props: ['options', 'value'],
});
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
<script type="text/x-template" id="component">
<div id="component">
<select :value="value" #input="$emit('input', $event.target.value)">
<option v-for='option in options' :value="option">
<slot v-bind="{ option }"></slot>
</option>
</select>
</div>
</script>
This works fine if the options are strings. However, if they are a different type (e.g. objects), then the values emitted are cast to strings (e.g. '[object Object]'). This is because $event.target.value pulls the value from the DOM, which will always be a string type.
Is there a way to get the original bound value of the selected <option>? I'm aware of v-model as an option, but it complicates things as it requires adding watchers.
EDIT I have discovered that Vue seems to assign the original bound value to the _value property on the DOM node, though I'm not sure if accessing that is a good idea since it's underscore prefixed and seems to be undocumented.
Let's say options prop is an array of object as below
You can change the event emitter of child component to return object instead of string like this:
<style>
[v-cloak] {
display: none;
}
</style>
<!-- // App -->
<div id="app">
<div v-cloak>
Value in parent: {{selectedValue}}
<br><br>
<custom-select :options='selectOptions' v-model='selectedValue'></custom-select>
</div>
</div>
<!-- // JS Code -->
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
<script type="text/x-template" id="component">
<div id="component">
<select #change="$emit('input', options.find(option => option.value == $event.target.value))">
<option v-for='option in options' :value="option.value">
{{ option.text }}
</option>
</select>
</div>
</script>
<script>
// Mount App
new Vue({
el: '#app',
data() {
return {
selectOptions: [
{ text: 'Apple', value: 'apple', price: '10' },
{ text: 'Banana', value: 'banana', price: '20' },
{ text: 'Strawberry', value: 'strawberry', price: '30' },
],
selectedValue: {}
}
},
// Custom component
components: {
'custom-select': Vue.component('custom-select', {
template: '#component',
props: ['options', 'value'],
})
}
})
</script>
While I still haven't found an exact solution to my original question, I've found a design pattern that I think solves the issue satisfactorily. By using a computed property with a getter and setter, I can use v-model on the <select> without needing watchers or any internal component state.
Vue.component('custom-select', {
template: '#component',
props: ['options', 'value'],
computed: {
valueProxy: {
get() {
return this.value;
},
set(newValue) {
this.$emit('input', newValue);
},
},
},
});
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
<script type="text/x-template" id="component">
<div id="component">
<select v-model="valueProxy">
<option v-for='option in options' :value="option">
<slot v-bind="{ option }"></slot>
</option>
</select>
</div>
</script>

Bootstrap Select not working inside Bootstrap Vue Modal

I am using Bootstrap Vue with Bootstrap select and the select works perfectly outside the modal
It doesnt open at all inside the modal. Live code is HERE
JS file
Vue.component("suluct", {
template: "#suluct",
props: {
week: [String, Number],
year: [String, Number],
},
mounted() {
const $selectpicker = $(this.$el).find('.selectpicker');
$selectpicker
.selectpicker()
.on('changed.bs.select', () => this.$emit('changeWeek', this.options[$selectpicker.val()]));
},
updated() {
$(this.$el).find('.selectpicker').selectpicker('refresh');
},
destroyed() {
$(this.$el).find('.selectpicker')
.off()
.selectpicker('destroy');
},
computed: {
options() {
// run some logic here to populate options
return [
{
title: "Sunday",
value: "sunday",
}, {
title: "Monday",
value: "monday"
}
]
}
}
})
new Vue({
el: "#app"
})
HTML
<div id="app">
<suluct></suluct>
<div>
<b-btn v-b-modal.modal1>Launch demo modal</b-btn>
<!-- Modal Component -->
<b-modal id="modal1" title="Bootstrap-Vue">
<suluct></suluct>
</b-modal>
</div>
</div>
<script type="text/x-template" id="suluct">
<select class="form-control selectpicker bs-select">
<option
v-for="(option, index) in options"
:key="index"
:value="option.value"
:selected="option.selected">
{{ option.title }}
</option>
</select>
</script>
The dropdown select wont open at all. Any help is appreciated
I had the same problem. After trying various ways, I found a solution.
When you wanna show modals, don not use v-b-modal directive.
Create a method, using this.$bvModal.show() to show modals.
And then you should use this.$nextTick([callback]) .
Final, use javascript to call bootstrap-select in the callback method
The method will be like
Html
<b-btn #click="ShowModal">Launch demo modal</b-btn>
Js
...
ShowModal() {
this.$bvModal.show('modal1');
this.$nextTick(()=>{
$('select').selectpicker();
})
},
...
ps:Sorry for my poor English and hope you can understand what I mean

how to use "v-for" for adding or removing a row with multiple components

i have a row with 3 components(in which is a defined component 1, component 2 and component 3, as showed in my previous question:
VueJs component undefined )
how can i add a row or remove a row (in which has 3 components) using v-for?
var data1={selected: null, items:["A", "B"]};
Vue.component('comp1', {
template: `<select v-model="selected">
<option disabled value="">Please select</option>
<option v-for="item in items" :value="item">{{item}}</option>
</select>`,
data:function(){
return data1
}
});
<!---similar for component 2 and 3--->
new Vue({
el: '#app',
data: {
rows:[]
},
methods:{
addRow: function(){
this.rows.push({});
},
removeRow: function(row){
//console.log(row);
this.rows.$remove(row);
}
},
});
in .html
<script src="https://unpkg.com/vue"></script>
<div id="app">
<div v-for ="row in rows">
<comp1></comp1>
<comp2></comp2>
<comp3></comp3>
<button #click="addRow">Add Row</button>
<button #click="removeRow(row)">Remove Row</button>
</div>
</div>
The code is pretty close. Try this.
console.clear()
const template = {
template: `<select v-model="selected">
<option disabled value="">Please select</option>
<option v-for="item in items" :value="item">{{item}}</option>
</select>`,
data: function() {
return {
selected: null,
items: ["A", "B"]
}
}
};
Vue.component("comp1", template)
Vue.component("comp2", template)
Vue.component("comp3", template)
new Vue({
el: '#app',
data: {
rows: []
},
computed:{
newId(){
return this.rows.length == 0 ? 1 : Math.max(...this.rows.map(r => r.id)) + 1
}
},
methods: {
addRow: function() {
this.rows.push({id: this.newId });
},
removeRow: function(row) {
this.rows.splice(this.rows.indexOf(row), 1)
}
},
});
<script src="https://unpkg.com/vue"></script>
<div id="app">
<div v-for="row in rows" :key="row.id">
<comp1></comp1>
<comp2></comp2>
<comp3></comp3>
<button #click="removeRow(row)">Remove Row</button>
</div>
<button #click="addRow">Add Row</button>
</div>
This code moves the add row button outside the loop, because you don't really need multiple add row buttons. Additionally, it adds a key for each div in the loop so that Vue can properly remove components when necessary. In order to generate the key, the code creates an id property for each new row object.

Clickable option with action in select

I'm working on a Vue file and have a select
<select v-if="show">
<option v-on:click="test()" value=""> someData</option>
<option>otherdata</option>
</select>
[...]
var instance = new Vue({
el: "#General",
[...]
methods:{
test: function(){
alert('youre goddam right');
}
[...]
}
[...]
}
So What i'm trying to do is to display my datas someData and otherdata. That works great but what i want it's when the user click on firstData, the action "test" append, and an alert comes up but that doesn't work here. I tried with the v-on:click but nothing happend.
Thanks for the help
Yes so it appears that the click event is not triggered for an <option> element. Here is one of the many fix available: using the input event on the select instead, and filter the value.
var instance = new Vue({
el: "#General",
methods:{
test: function(value) {
if (value === "choice1") {
alert('youre goddam right');
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
<div id="General">
<select v-on:input="test($event.target.value)">
<option value="choice1">someData</option>
<option>otherdata</option>
</select>
</div>