How to conditionally set a bootstrap-vue select box value when another select box value selected in vuejs? - vue.js

I am trying make a conditional select-box. There are 2 select-boxes. When select-box1 1's value changes then the 2nd select-box value automatically need to get selected to a value and it will also be disabled.
So far , i am able to do the conditional select where select-box 1's option changes value in select-box2 but it shows error in vue.
Error is--
[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: "value"
Also , i can disable the 2nd select-box but when i use dynamic disabled the value doesn't get set.
Question in brief:
1st selectbox has value-- a)one time payment & b)subscription and
2nd selectbox has value--a)held & b) Immediate.
Now, if 1st selectbox's subscription is selected then in the 2nd selectbox, it should be set to immediate and also get disabled.
Below is the Code Sandbox link--
https://codesandbox.io/s/conditional-select-forked-h61po?file=/src/components/HelloWorld.vue
If there is a better way of achieving this, then feel free to share ...

You don't need a ref, you can change the value of selected2 directly because it's not a prop, but a data field. Remove the reference in your component, like so:
<b-form-select
v-model="selected2"
:options="options2"
:disabled="isDisabled"
></b-form-select>
and change your onChange method to this (you don't need the else block as well):
onChange(event) {
if (event === "subscription") {
this.selected2 = "Immediate";
this.isDisabled = true;
}
},
Try it. I've tested it and it works.

I think the best way is to watch the 2-way-binding (selected) with a watcher.
See: https://v3.vuejs.org/guide/reactivity-computed-watchers.html#watch
And if the value changes you can check if the new value is 'subscription'.
And to select the wante option in the 2nd select you just have to asign the wanted value to the 2-way-binding (selected2). And for disabling set isDisabled to true.

Related

Select not rendering new :value when changing options dynamically with vuejs

I've created a small jsfiddle which explains the error and how to reproduce it here: https://jsfiddle.net/4Leu9a6x/57/
I have a select on which I use #change and :value to update and show the value. I know I could use v-model but my app is rather complex so this is the only way to do it currently.
The problems appears when I change the options dynamically. As soon as I change them the value of the select (the one the user sees) is not the same as the real value (saved in data by vue). Even though I do have :value.
I don't understand why it doesn't show a gray select (with nothing selected) when :value is not inside the options.
The jsfiddle above will clearly show this problem. Any ideas on how to keep the two in sync?
v-model has specific behavior to deal with the situation when a <select>'s options are changed dynamically. Since you're not using v-model, you'll have to deal with these issues yourself.
Like other input elements, a <select> has its own internal state (value and selectedIndex) that the browser maintains (not Vue). If you change the options without changing the value, then when Vue re-renders it won't set the value of the select since the value didn't change, so you're left with whatever state the browser chooses, and potentially the bound value will be out of sync with the actual value of the select.
A couple of solutions:
Bind key of the <select> to recreate the element when the options change (fiddle).
Wrap the <select> in a component and manually set the selectedIndex of the element to the index of the selected option. Read the v-model source to see how Vue does it.
When you change the options data, also change the value data so that it corresponds to an actual option. But this doesn't solve the problem of having the <select> select no option when the value doesn't match any option after changing the options but not the value.
Add this.val = this.options[0]; while running shuffle method. This is because each time the shuffle method runs it resets the options, since your value is not two way bound, the value is not being updated.
Else you can refractor your code and use v-model.
new Vue({
el: "#app",
data: {
val: 2,
options: [1, 2, 3, 4]
},
methods: {
shuffle() {
this.options = [Math.random(), Math.random(), Math.random()]
this.val = this.options[0];
}
}
})

how to solve vue short if in v-model?

I need to do a shortif in a v-model, but eslint gives the folowing problem:
[vue/valid-v-model] 'v-model' directives require the attribute value
which is valid as LHS.eslint-plugin-vue
so the code works. but its not the way it needs to work.
this is the code i have now
<v-text-field
v-show="field.type == 'String'"
v-model="_isMultiple(content_data[tabindex]) && subitem != null ? content_data[tabindex][subitem][field.name]
: content_data[tabindex][field.name]"
:label="field.name"
:counter="field.counter"
max-width="100px"
/>
So this code needs a little explanation to it.
I try to build this as an dynamic module. If I get an array back from my json response it needs to v-model the subitem. If I get an object back from the response it just needs to v-model that object.
The data (content_data[tabindex]) + field do i get from a v-for loop and other loops in my vue html
so I think its not an option to do a computed prop because
I can't get in the right data.
_isMultiple function code:
_isMultiple(content_data) {
return Array.isArray(content_data)
}
any solution for this?
Maybe you should not use v-model, but build it on your own with value binding and event listening.
v-model is only a shorthand: https://v2.vuejs.org/v2/guide/forms.html.
By implementing it on your own you can use a method to set the values and a computed property to get it.

How to auto-close date popup and hide div on selected change of element?

Rent Date doesn't auto close. It’s getting error as below. I'm not sure it's inside of the Div. Getting below error.
"[Vue warn]: Error in v-on handler: 'TypeError: $refs.qDateProxy.hide is not a function'
Want to hide the RentDate when user select Buy from individual Book’s Select Option. How should I change it? There will be multiple books.
Codepen
To auto close the date popup when user select on the date.
Hide 'RentDate' when user choose
You could use v-if or v-show for conditional hide show the Book RentDate on changes of boot type.
The directive v-if is used to conditionally render a block. The block will only be rendered if the directive’s expression returns a truthy value.
<h1 v-if="awesome">Vue is awesome!</h1>
Another option for conditionally displaying an element is the v-show directive. The usage is largely the same:
<h1 v-show="ok">Hello!</h1>
And for this error $refs.qDateProxy.hide, you can create a method and inside of this method you can use like below
onRentDateChange(){
this.$refs.qDateProxy[0].hide()
},
You can check here with working codepen.io.
EDIT
As per OP's comment, I have updated codepen.io. I have taken boolean variable inside of this.$data.Books array and used .find() method of array for changing variable status.
onValueChange(val,id){
let rec = this.$data.Books.find(({ID})=> ID==id);
if(rec) rec.isRentShow = val == 'Rent';
},

VueJs Getting emit value from a past event

I am emitting an event using an eventBus. I am looking to get the value from this on another component. At the moment, this triggers when something is selected, however, I want to be able to get the data from a Past event. For example, I have emitted the value when selecting an item. In another component, I wish to use this value again.
Here is the code to send the event:
clientId(client) {
eventBus.$emit("selected", client);
},
In the component, I am receiving it like this:
created() {
eventBus.$on("selected", index => this.client(index));
},
However it is not working for a past event.
I would like this to update a data value in a different component so that i can use the value.
How can I get the value of a past event?
You need a store for preserving data, simply inside your event bus update the store and then you can use a getter to retrieve the data from the store in any component. If you are not familiar take a look at the vuex docs.

Vue: My initial data value is not accessible when used as a function param

I am having an issue when triggering the click handler in my button here. The error comes back as TypeError: Cannot read property 'discountProduct' of null when I click the button. I know for a fact that this.discountProduct.id has a value by inspecting it from the Vue Tools and by knowing that the button is rendering to begin with since it only conditionally shows if the id > 1.
I alternatively tried to remove this but it still throws the same error.
I also tried manually just inserting the product id as the param and that works so I am not sure what the issue is at this point.
<button v-if="this.discountProduct.id >= 1"
type="button"
v-on:click="addToCart(this.discountProduct.id, true)"
Is you button in the <template> tags?
If so, you do not need to use this delete from the click argument and v-if. However that should only throw a warning.
Can you also post the code for the method addToCart?
If you are not setting the full discountProduct object you will need to make sure setting the id is reactive. Like the example below:
this.$set(this.discountProduct, 'id', 1)
Nested Object/keys are not reactive without using $set. See https://v2.vuejs.org/v2/guide/reactivity.html for more details.
Hope this helps