how to solve vue short if in v-model? - vue.js

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.

Related

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

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.

Vue js - is that right to put all my code in watch?

I Have component A and Component B
in component A i have an API call.
when i passing info to my component b:
<B :structuresMetaData="structureTree"></B>
Inside mounted the variable structuresMetaData the length is 0
and inside the watch the length is 1.
my issue that mounted appear before the watch.
is it would be right to put all my code in watch ? if not what is the solution ?
It looks like structureTree is being changed after <B> is created/mounted.
You have two options depending on your use case:
The first option is to defer the creation of <B> until your data is loaded. This way you don't need <B> to watch for changes to the prop and the prop will be fully populated in the created/mounted hook. This is the simpler approach.
Assuming structureTree is initially an empty array:
<B
v-if="structureTree.length > 0"
:structuresMetaData="structureTree"
/>
created() {
// this.structuresMetaData is a non-empty array here
}
I usually initialize my data with null so that I can distinguish between "not loaded" and "loaded" (where "loaded" can actually be an empty array if the data I fetched from the API was empty).
The second way is using a watcher in <B> to react to changes to the prop. You will need to do this method if the bound prop might change multiple times and you need <B> to update in some way to that change.
watch: {
structuresMetaData(value) {
// React to the change, load secondary data, etc
}
}
What exactly are you doing in <B> that requires a watcher? It's best to avoid explicit watchers if you can avoid them because it usually means you are copying data around and it gets messy when you don't have a single source of truth. Use pure computed properties whenever you can if you just want to transform the data in some way.

is there a way to pass muttiple values which are not in side a component(dom)?

I am very new to Vue,
i tried to simulate this in bellow link.
https://jsfiddle.net/kyncgL7w/9/
I have this simple html select tag. Where I am showing values from object(banks).
now I have used v-on:change so when ever user will select any values, i want to get values of
> ledger_object_type_sub_id and ledger_object_type_sub_name
Now, I can get the ledger_object_type_sub_id from v-bind or v-model,
but how do i pass the value of ledger_object_type_sub_name into a function.
i.e get_existing_bank_id(bank_name_id, **bank_name**) so that i can use that value can be use later on?
Thanks for your help.
Just bind object value on your option tag
<option v-bind:value="bank">..</option>
What you can do is to find in your banks array the ledger_object_type_sub_id who is equal to your bank_name_id.
get_existing_bank_id: function(bank_name_id) {
console.log(this.banks.find(bank => bank.ledger_object_type_sub_id === bank_name_id).ledger_object_type_sub_name);
}
Here is your fiddle update with the working solution : https://jsfiddle.net/sjh038w9/

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

VueJS Component Input Sync

I want to create components which have input which two-way bind to the local scope of the component.
Without a component, I would create a new Vue instance and then set my data to what I need. Then using v-model, bind an input to that data and it can be manipulated from the input.
However, converting the same code to a component, I cannot for the life of me get any input in a component to bind to its data. I have tried props, :data.sync, data attributes but no matter what I have tried, the input within a component does nothing.
I have created a JSFiddle to illustrate this:
https://fiddle.jshell.net/f0pdmLhy/2/
What I would like to happen is the input in the component to two way bind to the err variable, just like the non component version underneath.
How would I accomplish this?
I basically want to create components that I can instansiate with ajax data and then populate the inputs. The inputs could then update the data and I can use a save method to send the data to the server. Can this even be done using components?
So there are a couple of things:
The external resource you were using was somehow faulty. I've used
jsfiddle default Vue instance and it works fine.
When you declare a component, you should not define the data as an object, but as a function returning an object. Read here: https://vuejs.org/guide/components.html#Component-Option-Caveats
A working example here: https://fiddle.jshell.net/by4csn1b/1/
Yes, with components, the reactivity can be accomplished just like with an instance.
One catch with components, is that data must be a function that returns an object.
Also, to maintain the two way binding, use v-model in your input.
Vue.component('ii', {
template: '<span>{{err}}</span><input type="text" v-model="err"><hr>',
data: function () {
return {
err: 123
}
}
})
Fiddle: https://fiddle.jshell.net/f0pdmLhy/25/