vue escaping object child as parameter - javascript

I want to build a helper function to reduce my redundant code lines.
Instead of doing nearly the same over and over i want to use that function to simple add a parameter and reduce the lines of code.
<template>
<div>
<!-- TODO: ADD ALL PROPS NOW! -->
<UserInfo
:user-name="userData.userName"
:budget="userData.budget"
:leftover="userData.leftover"
/>
<UserIncExp />
</div>
</template>
<script>
import UserInfo from '../User/UserInfo.vue';
import UserIncExp from '../User/UserIncExp/_UserIncExp.vue';
export default {
components: {
UserInfo,
UserIncExp
},
data() {
return {
test: '',
userData: {
userName: '',
budget: '',
leftover: '',
inc: [],
exp: [],
active: false
}
};
},
computed: {},
watch: {
'$route.params.userId': {
handler() {
this.loadUserDataFromState();
}
},
immediate: true
},
created() {
this.loadUserDataFromState();
},
methods: {
loadUserDataFromState() {
// this.userData.userName = this.$store.state.users[this.$attrs.userId].userName;
// this.userData.budget = this.$store.state.users[this.$attrs.userId].salery;
// this.userData.leftover = this.$store.state.users[this.$attrs.userId].leftover;
this.helper(userName);
},
// CHECK HERE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
helper(data) {
return this.userData.data = this.$store.state.users[this.$attrs.userId].data;
}
}
};
</script>
<style>
</style>
but i dont get why i am not able to use data as an parameter to use it then in the executed function

Use bracket notation like so:
loadUserDataFromState() {
this.helper("userName");
},
helper(key) {
this.userData[key] = this.$store.state.users[this.$attrs.userId][key];
}
helper expects a key (which is a string).
Note: helper doesn't need to return anything.
An alternative way which doesn't require the function helper at all is to use a loop over an array of keys like so:
loadUserDataFromState() {
for(let key of ["userName", "salery", "leftover"]) {
this.userData[key] = this.$store.state.users[this.$attrs.userId][key];
}
}
it just loops over the keys in the array ["userName", "salery", "leftover"] and dynamically copy the values from the source object to this.userData.

Related

Why Vue can't watch the data change?

i want the function:createComparation work when tableRowName change,but acturely when tableRowName change , it didnt works,vue follows;
createComparation is another function which didnt define by vue but only by javascript
const selectedRight =Vue.createApp({
data(){
return {
tableRow:0,
tableRowName:[],
stockName:[],
rectWidth:40,
rectHeight:5,
}
},
watch: {
tableRowName(newtable,oldtable){
console.log(1)
createComparation()
},
immediate:true,
stockName(){
changeTip()
},
},
methods:{
}
}).mount('#selectedRight')
in case of tableRowName contain objects then you have to use
deep:true
watch: {
tableRowName(newtable,oldtable){
console.log(1)
createComparation()
},
immediate:true,
deep: true,
stockName(){
changeTip()
},
},
but i think you are updating the array without reactive manner, Vue cannot detect the following changes to an array:
When you directly set an item with the index, e.g.
vm.items[indexOfItem] = newValue
When you modify the length of the array, e.g.
vm.items.length = newLength
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // is NOT reactive
vm.items.length = 2 // is NOT reactive
I guess whatching array might be the issue. You can try this:
computed: {
rowNames() {
return this.tableRowName;
// if the line above doesn't work:
return this.tableRowName.join();
}
},
watch: {
rowNames(newtable,oldtable){
createComparation()
},
I think this is what you're looking for. You need to define the handler as an object for the property you're trying to watch and set immediate: true.
Vue.config.productionTip = false
Vue.config.devtools = false
new Vue({
el: "#app",
data() {
return {
tableRow: 0,
tableRowName: [],
stockName: [],
rectWidth: 40,
rectHeight: 5,
}
},
watch: {
tableRowName: {
handler(newtable) {
console.log('Calling createComparation function');
console.info(newtable);
},
immediate: true
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="tableRowName.push(Math.random())">Trigger change manually again</button>
</div>
The watch method definition is wrong. When you need to use immediate, you have to put you function body into handler property.
For example,
watch: {
tableRowName: {
handler: function() {
},
immediate: true
}
},

Use props with forEach in vuejs

I'm desperately trying to use my props 'datas' with a foreach.
When I put my data in a "test" data, it works.
Example :
data() {
return {
postForm: this.$vform({}),
test: [{"name":"Couleur yeux","id":3,"answer":null},{"name":"Hanches","id":6,"answer":"'Test'"}],
}
},
computed: {
},
methods: {
createForm() {
this.test.forEach((data) => {
if (data.answer) {
this.$set(this.postForm, data.id, data.answer)
}
})
}
},
But if I use my props directly, it doesn't work. I have a message "this.datas.forEach is not a function".
But my props has exactly the same data and the same structure as my "test" data.
Don't work:
this.datas.forEach((data) => {
if (data.answer) {
this.$set(this.postForm, data.id, data.answer)
}
})
I also tried to transform my props into data() but it doesn't work
data() {
return {
postForm: this.$vform({}),
test: this.datas
},
"this.datas.forEach is not a function"
This mean that datas is not an Array instance because forEach is method from array prototype.
Right now, this.datas does not exist. You never give this the state with the key datas.
It looks like you're trying to go through this.test, which is an array of objects. Is that right?
If that's the goal, you can do so:
data() {
return {
postForm: this.$vform({}),
test: [{"name":"Couleur yeux","id":3,"answer":null},{"name":"Hanches","id":6,"answer":"'Test'"}],
}
},
methods: {
createForm() {
let arrayOfAnswers = []
this.test.forEach((data) => {
if (data.answer) {
arrayOfAnswes.push(data.answer)
}
})
this.arrayOfanswers = arrayOfAnswers
}
},

Use object properties as parameters to GET request

Right now I have this two components:
pesquisar.vue
form.mb-3(#submit.prevent="getPessoaFisica(object)")
Search(:object='object')
button.btn.btn-sm.btn-success.d-none(type="submit")
.fa.fa-search
...
data() {
return {
object: {
Cd_Pessoa: null,
Nm_Pessoa: null,
Nm_Apelido: null,
Nr_Documento: null,
Nm_Officer: null,
Tp_Registro: null,
Cd_TipoID: null,
},
page: undefined,
list: undefined,
};
},
methods: {
getPessoaFisica(obj, page = 1, count = 18) {
this.$axios
.get("/pessoaFisica", {
params: {
obj,
page,
count
}
})
.then(res => {
this.list = res.data;
});
}
},
search.vue
<template lang="pug">
.row(#input="$emit('input', object)")
.col-md-4.mb-1(v-for='property in Object.keys(object)')
.row
.col-auto.pr-0 {{property}}:
.col
input.form-control.form-control-sm.py-0(v-model='object[property]')
</template>
<script>
export default {
props: ['object']
}
</script>
I'm using the object object in pesquisar.vue to dynamically create inputs in my view.
When I submit the form with random data, I'm getting this request:
http://localhost/abc?obj=%7B%22Cd_Pessoa%22:null,%22Nm_Pessoa%22:%22her%22,%22Nm_Apelido%22:null,%22Nr_Documento%22:null,%22Nm_Officer%22:null,%22Tp_Registro%22:null,%22Cd_TipoID%22:null%7D&page=1&count=18
What I really wanted was this:
http://localhost/abc?Nm_Pessoa:"her"&page=1&count=18
Basically what I wanted was to use the object properties as parameters to GET request.
Any help, please?
Try spreading the object properties using the object spread operator ...obj:
// ...
this.$axios
.get("/pessoaFisica", {
params: {
...obj,
page,
count
}
})
.then(res => {
this.list = res.data;
});

Vue v-for on first item containing property X call a method

Let's say I have a component which repeats with a v-for loop like so:
<hotel v-for="(hotel, index) in hotels"></hotel>
And my hotels array would look like so:
[
{
name: false
},
{
name: false
},
{
name: true
},
{
name: true
}
]
How could I perform an action when my v-for loop encounters the property name set to true only on the very first time it encounters this truthy property?
I know I could probably cache a property somewhere and only run something once and not run again if it has been set but this does not feel efficient.
Use a computed to make a copy of hotels where the first one has an isFirst property.
computed: {
hotelsWithFirstMarked() {
var result = this.hotels.slice();
var first = result.find(x => x.name);
if (first) {
first.isFirst = true;
}
return result;
}
}
Just use computed source
HTML
<div v-for="(hotel, index) in renderHotels"></div>
JS
export default {
name: 'message',
data () {
return{
hotels:[
{
name: false
},
{
name: false
},
{
name: true
},
{
name: true
}
] ,
wasFirst : false
}
},
methods:{
},
computed:{
renderHotels(){
return this.hotels.map((hotel)=>{
if(hotel.name && !this.wasFirst){
this.wasFirst = true;
alert('First True');
console.log(hotel);
}
})
}
}
}
Best way is to use filter function.
data() {
return {
firstTime: false,
};
},
filters: {
myFunc: function (hotel) {
if (hotel.name && !this.firstTime) {
//perform some action
this.firstTime = true;
}
}
}
<hotel v-for="(hotel, index) in hotels | myFunc"></hotel>

Update data property / object in vue.js

is there a way I can programmatically update the data object / property in vue.js? For example, when my component loads, my data object is:
data: function () {
return {
cars: true,
}
}
And after an event is triggered, I want the data object to look like:
data: function () {
return {
cars: true,
planes: true
}
}
I tried:
<script>
module.exports = {
data: function () {
return {
cars: true
}
},
methods: {
click_me: function () {
this.set(this.planes, true);
}
},
props: []
}
</script>
But this gives me the error this.set is not a function. Can someone help?
Thanks in advance!
Vue does not allow dynamically adding new root-level reactive properties to an already created instance. However, it’s possible to add reactive properties to a nested object, So you may create an object and add a new property like that:
data: function () {
return {
someObject:{
cars: true,
}
}
and add the property with the vm.$set method:
methods: {
click_me: function () {
this.$set(this.someObject, 'planes', true)
}
}
for vue 1.x use Vue.set(this.someObject, 'planes', true)
reactivity

Categories