VueJS router $routes.push can't push query params - vue.js

Why on earth this doesn't work?
selectChanged(val) {
let term_ids = [];
let taxonomy = '';
val.forEach((obj) => {
term_ids.push(obj.term_id);
taxonomy = obj.taxonomy;
});
let obj = this.$route.query;
obj[taxonomy] = term_ids.join(',');
this.$router.push({
query: obj,
});
},
obj looks like this:
{education_levels: "33,36", candidate_countries: "304"}
If I hardcode above object it will work as intended, VueJS Router will push query string and it will look like this: ?education_levels=33,36&candidate_countries=304
But if I pass query: obj nothing will happen...

You need to assign all the properties with route.
Object.Assign makes a new COPY of the of the $route, including all enumerable OWN properties
One more suggestion -
When you do this let obj = this.$route.query; -
Objects get stored to memory so when you try to copy an object you are actually copying the address of the object where that stored in memory.
So when you do this - obj[taxonomy] = term_ids.join(',');
You will accidently mutate the original value, so cloning required
Instead clone it-
let obj = { ... this.$route.query }
this.$router.push({
query: Object.assign({}, this.$route.query, obj),
});

Related

vuex + vuexfire - store objects would not update upon adding data

in the folowing code, after i update field collection it would not
update "this.fields" (which is bound to tha collection in store.js by
vuexfire rules) - only when i refresh page. please help. thanks
var newField = {
name: this.fieldName,
area: this.fieldArea,
farmId: this.farmId
}
var docRef = fb.field.doc()
docRef.set(newField)
var id = docRef.id
console.log(id)
fb.field
.doc(id)
.get()
.then(ref => {
this.$store.commit('updateCurrentField', ref.data())
})
How, and where, are you getting the this.fields?
Is it a computed property?
it should be somthing arround the lines of this in order to keep the data updated (vuex documentation)
computed: {
fields() {
this.$store.state.fields
}
}

Computed Property causes array and object mutation

I am trying to pass data to a v-select dropdown.
This of course works:
computed: {
itemDropdown() {
const menuItems = {
id: "1",
name: "Joe"
}
return menuItems;
}
}
But when I try:
computed: {
itemDropdown() {
const newArray = [...this.data.originalItems];
newArray.map(item => {
item.name = "myCoolNewName";
});
return newArray;
}
}
It mutates the original array.
I have also tried copying the object:
computed: {
itemDropdown() {
const newObj = { ...this.data };
newObj.items.map(item => {
item.name = "myCoolNewName";
});
return newObj;
}
}
Not sure what I’m missing, but wondering if there is a work around. Thanks for any help :slight_smile:
You are using the map array method wrong.
The first thing you need to know, is that the map method returns a new array, so you have to either return the result of your map function or save it in a variable, otherwise you will just be looping through your array without ever saving it anywhere.
Another thing is about how you use the map method.
Here I have made an example of how it should work with your code:
computed: {
itemDropdown() {
return this.data.originalItems.map(item => {
return {
name: "myCoolNewName"
}
});
}
}
The big difference you should notice, is that inside the map function, we have to return what we want each object to look like, after we have gone through it. We want it to give us the object back, but make some changes to it, so we have to actually return an object and change what we want in that.
What you were doing before, was refering to the item in the old array, and assigning it a new value, instead of returning a new object with your changes.
You can read about the array.map method here
Hope that makes sense :)

Async data fetching not updating reactive data property

Ok, guys, I´m having a little issue today, all day long, trying to solve, the deal goes like this...
I´m fetching some data from firebase to render on the html template with asynchronous functions
I have a fetchList Method that is like this:
async mounted() {
let ret = await this.fetchJobRequireList()
console.log('fetchjoblist' , ret)
async fetchJobRequireList() {
// debugger
let services = JSON.parse(sessionStorage.getItem('required_services'))
services != null ? this.required_services = services : null
let docs_ = []
let result = []
if (!services) {
// this.required_services = []
// get required services per user id
let collections = this.$options.firebase.functions().httpsCallable('getRequiredServices')
let docs = await this.$options.firebase.firestore().collection('required_services').get()
// console.log('required services docs', docs)
let _ = this
for (let doc of docs.docs) {
result[doc.id] =
await collections({doc_id: doc.id}).then( async r => {
// debugger
let collections_ = r.data.cols
docs_ = []
_.required_services[doc.id] = []
for (let collection of collections_) {
let path = collection._referencePath.segments
// let documents =
let __ = _
await this.$options.firebase.firestore().collection(path[0])
.doc(path[1]).collection(path[2]).get()
.then(async documents => {
// console.log('__documents__', documents)
for (let doc_ of documents.docs) {
doc_ = await documents.docs[0].ref.get()
doc_ = {
id: doc_.id,
path: doc_.ref.path,
data: doc_.data()
}
// debugger
__.required_services[doc.id].push(doc_)
console.log("this?", this.required_services[doc.id], '__??', __.required_services)
docs_.push(doc_)
}
})
}
console.log('__docs__', docs_)
return docs_
}).catch(err => console.error(err))
// console.log('this.required_services', this.required_services)
}
}
// console.log('object entries', Object.entries(result))
// console.log('__this.required_services__', Object.entries(this.required_services))
// sessionStorage.setItem('required_services', JSON.stringify(this.required_services))
return result
}
The expected result would be for the data function properties to be update after the firebase response came, but no update is happening.
If anyone, have any clues, of what could be happening... some people told me that asynchrounous functions could cause problems... but there is no alternative for them, I guess...
This line
_.required_services[doc.id] = []
is not reactive. See the first point in the docs
So as pointed by #StephenThomas, there is some limitations in array change detection capabilities in reactive property usage.
So after loading the content from firebase, try to push it like this.joblist.push(doc) vue property will not react properly and make some confusion in the head of someone that doesn´t know about this limitation in detecting this kind of array mutation (https://v2.vuejs.org/v2/guide/list.html#Caveats)...
By using this line, now is possible to see the changes in property inside the Vue dev tools
_.joblist.splice(0,0, local_doc)
Thanks #SthephenThomas, for pointing this out!!

Vue.js - can't access the properties of a prop object

I am creating then passing an object using pdfjs in to a child Vue component. When I do so, I can access the object itself, but I cannot access any properties of the object.
This is the case during all of the lifecycle hooks.
<i-slide-deck-pdf // calling child vue component
v-if="true"
:slideDeckItem="fetchPDF('/static/intropdf.pdf')"
:current-user-progress="currentUserProgress"
#i-progress="putProgressTracker"
#i-slide-change="onSlideChange"
/>
...
fetchPDF(url) { // function being used to create the object
let pdfItem = new Object();
import(
'pdfjs-dist/webpack'
).
then(pdfjs => pdfjs.getDocument(url)).
then(pdf => {
pdfItem.pdf = pdf;
pdfItem.pages = range(1, pdf.numPages).map(number => pdf.getPage(number));
pdfItem.pageCount = pdfItem.pages.length;
})
return pdfItem;
},
...
props: { // prop call in child component
slideDeckItem: {
type: Object,
required: true
},
}
Console log
Thanks in advance.
This is because the async call hasn't completed, so you are just returning an empty object, to fix this you want to set a value inside the then portion of your code, and bind this to your prop, so:
fetchPDF(url) { // function being used to create the object
let pdfItem = new Object();
import(
'pdfjs-dist/webpack'
).
then(pdfjs => pdfjs.getDocument(url)).
then(pdf => {
pdfItem.pdf = pdf;
pdfItem.pages = range(1, pdf.numPages).map(number => pdf.getPage(number));
pdfItem.pageCount = pdfItem.pages.length;
// This should be inside the "then"
this.slideDeckItem = pdfItem;
})
},
You'll then want to declare slideDeckItem in your parent data property, and bind that to your component's prop:
<i-slide-deck-pdf
v-if="true"
:slideDeckItem="slideDeckItem"
:current-user-progress="currentUserProgress"
#i-progress="putProgressTracker"
#i-slide-change="onSlideChange"
/>
I've made a JSFiddle, to give you the basic idea, although I've used a timeout to simulate the async call: http://jsfiddle.net/ga1o4k5c/
You may also want to take a look at how Promises work

find subdocument without start from parent

Pretty new to mongoose. Can I findOne off of a subdocument model?
I have a subdoc called deliverables which is a child of projects
What I'd like to do is FIND on my deliverables model so I don't have to find on the project as
{project.child.child.child.deliverables._id: req.id}
Is that possible or do I have to start from the project model each time? Below is a sample setup I'm using along with my example findOne.
'use strict';
//////////////model/////////////////
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var deliverablesSchema = new Schema({
title:{
type:String,
}
})
var ProjectSchema = new Schema({
name: {
type: String,
},
deliverables: [deliverablesSchema],
});
mongoose.model('Deliverable', deliverablesSchema);
mongoose.model('Project', ProjectSchema);
//////////////controller/////////////////
var mongoose = require('mongoose'),
Project = mongoose.model('Project'),
Deliverable = mongoose.model('Deliverable'),
_ = require('lodash');
exports.findDeliverable = function(req, res) {
Deliverable.findOne({'_id': req.params.deliverableId}).exec(function(err, deliverable) {
if(deliverable){
//return
}
});
};
You can find subdocuments within a document only if you have declared their schema http://mongoosejs.com/docs/subdocs.html
Here is an example taken from here:
Project.findOne({
'_id': myid
}).exec(function (err, p) {
if (p) {
//return
var deriv = p.deliverables.filter(function (oneP) {
return oneP._id === 'myderivableid';
}).pop();
}
});
If your subdocuments are just nested objects in an array you may use Lodash to retrieve that data using _ .where or _.find
Kept digging and found this:
https://stackoverflow.com/a/28952991/2453687
You still have to pull the master document first but it's easy to drill down to the particular object you're looking for and make a quick update, then just update the whole master document in one shot.
Dead simple. Works like a charm.