Is there a way to pass vue model values into method function? - javascript

I recently started using Vue Js and I am stuck at this point where I cant pass vue model values to method function.
<div v-for="(post, index) in posts" :key="post.customerName">
<input type="text" v-model="post.customerName" /> /** successfully print customerName inside this field**/
<b-button block pill variant="outline-info" v-on:click="bookerName()">
{{post.customerName}}
</b-button>
</div>
Method Function
bookerName(){
console.log(this.post.customerName); /** prints out UNDEFINED **/
}
VUE data return
posts:{
customerName:{ 'David','John','Sam'},
},
bookerName: ''

Pass the index from v-for to the method, and get the value by index:
<b-button v-on:click="bookerName(index)">
...
bookerName (index){
console.log(this.posts[index])
}
Also, in your example you have bookerName: ''. Is it a property inside data()? If so, you cannot have method with the same name bookerName

Related

How do I access the dynamic template refs that are nested in Vue 3?

I have a custom list component gcl-list that uses a v-for to render a passed template for each item in an array. Ive nested one of these components in another and am trying to access refs on the children gcl-list-items to then edit the innerHTML but when I access that ref it gives me a string representation of the element which I cant edit the inner HTML. How would I access that childs span and change its innerHTML?
Output to console when logging childItemRefs.value:
Proxy
handler: {get: function, set: function, deleteProperty: function, has: function, ownKeys: function}
target: Array (2)
0 <span data-v-2b58c258>Three.One</span>
1 <span data-v-2b58c258>Three.Two</span>
Code:
<gcl-list :listArray="filteredDropdownItems">
<template v-slot="itemData">
<gcl-list-item
selectable
:indeterminate="itemData.item.indeterminate"
:checked="itemData.item.selected"
:iconStart="itemData.item.iconStart"
:iconEnd="itemData.item.iconEnd"
#click.stop
#click="onItemClick(itemData.item)"
>
<span :ref="el => itemRefs[filteredDropdownItems.indexOf(itemData.item)] = el">
{{ itemData.item.displayValue }}
</span>
</gcl-list-item>
<gcl-list v-if="itemData.item.childItems" :listArray="filteredChildren(itemData.item.childItems)">
<template v-slot="childItemData">
<gcl-list-item
selectable
nested
:checked="childItemData.item.selected"
:iconStart="childItemData.item.iconStart"
:iconEnd="childItemData.item.iconEnd"
#click.stop
#click="onChildItemClick(childItemData.item, itemData.item)"
>
<span :ref="el => childItemRefs[filteredChildren(itemData.item.childItems).indexOf(childItemData.item)] = el">
{{ childItemData.item.displayValue }}
</span>
</gcl-list-item>
</template>
</gcl-list>
</template>
</gcl-list>
```
[1]: https://i.stack.imgur.com/1dFTx.png

null value in dynamic v-for with functional template refs

Situation
I am building a custom filtering component. This allows the user to apply n filters that are displayed with a v-for in the template. The user can update any value in the input fields or remove any of the filters afterwards.
Problem
After removing one of the filters, my array itemRefs got a null value as the last item.
Code (simplified)
<script setup>
const filtersScope = $ref([])
const itemRefs = $ref([])
function addFilter () {
filtersScope.push({ value: '' })
}
function removeFilter (idx) {
filtersScope.splice(idx, 1)
itemRefs.pop() // <- necessary? has no effect
// validate and emit stuff
console.log(itemRefs)
// itemRefs got at least one null item
// itemRefs = [null]
}
// assign the values from the input fields to work with it later on
function updateValue() {
itemRefs.forEach((input, idx) => filtersScope[idx].value = input.value)
}
</script>
<template>
<div v-for="(filter, idx) in filtersScope" :key="filter.id">
<input
type="text"
#keyup="updateValue"
:ref="(input) => { itemRefs[idx] = input }"
:value="filter.value"
>
<button #click="removeFilter(idx)" v-text="'x'" />
</div>
<button #click="addFilter()" v-text="'add filter +'" />
</template>
>>> Working demo
to reproduce:
add two filters
itemRefs got now the template refs as a reference, like: [input, input]
remove one filter, itemRefs now looks: [input, null]
remove the last filter, itemRefs now looks like: [null]
Question
Without the itemRefs.pop() I got the following error, after removing and applying new filters:
Uncaught TypeError: input is null
With the pop() method I prevent a console error, but the null-value in itemRefs still remains.
How do I clean my template refs cleanly?
I don't know what's up with using $refs inside $refs but it's clearly not working as one would expect.
However, you should never need nested $refs. When mutating data, mutate the outer $refs. Use $computed to get a simplified/focused angle/slice of that data.
Here's a working example.
<script setup>
const filtersScope = $ref([])
const values = $computed(() => filtersScope.map(e => e.value))
function addFilter() {
filtersScope.push({ value: '' })
}
function removeFilter(idx) {
filtersScope.splice(idx, 1);
console.log(values)
}
</script>
<template>
<div v-for="(filter, idx) in filtersScope" :key="idx">
<input type="text"
v-model="filtersScope[idx].value">
<button #click="removeFilter(idx)" v-text="'x'" />
</div>
<button #click="addFilter()" v-text="'add filter +'" />
</template>

Vue3 How to pass input's value to method in #change="func(param)"?

I have an input field and I need to call the function every time when value is changed and pass the new value to the function. I couldn't find how to do it.
<template slot-scope="scope">
<el-input
type="text"
:value="scope.row.name"
v-model="queryName"
#change="changeQueryName(scope.row.id, ???.queryName)">
</el-input>
</template>
You can pass the $event
#change="changeQueryName($event, scope.row.id, ???.queryName)"
This is de doc HTMLElement: Event
In the changeQueryName() function you can use event.target.value
changeQueryName(event, id, queryName) {
console.log(event.target.value)
}

Not able to pass string to formGroup

1.I want to loop through an array
*ngFor="let item of myformNameArray"
Think myformNameArray.length have 3 items
If I console item it will be like
myFormName1
myFormName2
myFormName3
I have already made these form group in my typescript component.
Example
<form [formGroup]="myFormName3">
It will work perfectly!!
But i want to loop :means
<div *ngFor="let item of myformNameArray">
<form [formGroup]="{{item}}">
</form>
</div>
So when I do,
[formGroup]="{{item}}"
It throws me an error can't assign to object or interpolation
Or
[formGroup]="see(item)"
Where ,
see(item) :string {
return String(item);
}
ERROR TypeError: can't assign to property "validator" on "see(item)": not an object
[formGroup] requires a FormGroup Object not string
you need to make array of formgroups instead of string names
TS:
myformArray = [
this.myFormOne,
this.myFormTwo,
this.myFormThree
]
HTML:
<div *ngFor="let item of myformArray">
<form [formGroup]="item">
</form>
</div>
you can also use formArray instead of normal array
TS:
myFormArray = new FormArray([]);
this.myFormArray.push(myFormOne);
this.myFormArray.push(myFormTwo);
this.myFormArray.push(myFormThree);
HTML:
<div *ngFor="let form of myFormArray.controls;">
<form [formGroup]="form">
<input formControlName="controlOne" />
<input formControlName="ControlTwo" />
</form>
</div>
And also you should not use both square brackets and curly brackets (interpolation) for property binding, use either square brackets or interpolation.
internally angular converts square brackets to interpolation
either do this : [formGroup]="item"
or this : formGroup="{{item}}"
not both

How can i change the attribute of a field in Ember JS from a route

In My application i have a template file with 2 fields(say name1 / name2).
Based on one parameter("preference") in the route i want to display either Recipe1 or Recipe2 on the screen.
For eg: if preference is veg, i should display Recipe1 else Recipe2.
i tried this as below but it did not work.
export default Ember.Route.extend({
beforeModel(){
if (preference==='veg'){
console.log("Inside Veg..");
Ember.$("#Recipe2").attr("type","hidden");
}
else {
console.log("Inside Non Veg..");
Ember.$("#Recipe1").attr("type","hidden");
}
What i see is that it goes inside the if/else loop but the ember.$ statements dont make any difference.Please help.
First of all you should not write Ember.$ inside beforeModel hook. that's wrong. When beforeModel hook called, DOM will not be ready. I prefer you to create component and pass preference property to component and have if check to display it in hbs
Create my-receipe component and include it in template.hbs
{{my-receipe preference=preference }}
my-receipe.hbs
{{#if isVeg}}
<input type="text" id="Recipe1" />
{{else}}
<input type="text" id="Recipe2" />
{{/if}}
my-receipe.js
Create isVeg computed property which will return true if the preference is veg.
export default Ember.Component.extend({
isVeg: Ember.computed('preference', function() {
return Ember.isEqual(this.get('preference'), 'veg');
})
})

Categories

Resources