calling an array method on a computed property - vue.js

I have an array:
const arr = []
I then have a computed property:
const filtered_arr = computed(() => {
//...
}
I then have another computed property: filtered_arr2 where I want to call some() method on the first filtered_arr.
But getting errors since filtered_arr is not an actual array.
const filtered_arr2 = computed(() => {
filtered_arr.some((e)=>{}) // <- error
}
UPDATED:
Getting several errors :
some is not a function
Container is not set or can not be properly recognized. Use container() method to set it
I think my whole approach is buggy...

From the API documentation...
computed()#
Takes a getter function and returns a readonly reactive ref object
and
ref()#
Takes an inner value and returns a reactive and mutable ref object, which has a single property .value that points to the inner value
So with that in mind, you'll need to use the .value property within your setup
const filtered_arr = computed(() => {
// return some array
});
const filtered_arr2 = computed(() => {
const isPresent = filtered_arr.value.some(...);
// return some other value
});

Related

Is there any way to return an entire namespace via the translate function in i18next?

in my case,i need get the entire namespace as an object,is there any can do this?
i have try this code,but just return undefined。
// the bookingPage is a namespace
t('bookingPage',{ returnObjects: true })
It is not possible with the t function, t function returns a string.
You can get an access to the entire i18n object which has methods for this.
// your-component.jsx
const YourComp = () => {
const { i18n } = useTranslation();
console.log(i18n.store.getResourceBundle('en', 'bookingPage')); //<-- will return the entire namespace
return <div>Bla</div>;
};

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

Why "Error in render: TypeError: Cannot read property 'filter' of undefined" returned even data already available?

I already initialize the data.
data () {
return {
current_product: {},
current_ID: '',
}
}
Then, I fetch data from a REST API on lifecycle created hook.
created () {
var skuID = this.$store.state.selected_productSKU.productSKU_ID
axios.get(`http://localhost:8081/api/products/${skuID}`)
.then(response => {
this.current_ID = response.data.product_ID
this.current_product = response.data
})
.catch(e => {
alert(e)
})
}
And finally, I use computed property to get some value
// THIS JUST RETURN ['XL', 'M']
focusedProduct_SKUS_NoDupSizes () {
var newArr = this.current_product.product_SKU.filter((sku, index, self) =>
index === self.findIndex(t => (
t.productSKU_size === sku.productSKU_size
))
)
var x = newArr.map(a => a.productSKU_size)
return x
}
The vue instance show expected result
But if i call {{ focusedProduct_SKUS_NoDupSizes }} in template.
It doesn't rendered.
The browser return error Error in render: "TypeError: Cannot read property 'filter' of undefined"
What is happening? My first guess is the computed property using the initial structure of current_product which is {} empty object. But isn't that how to initialize an object?
Because of:
computed:
// ...
focusedProduct_SKUS_NoDupSizes () {
var newArr = this.current_product.product_SKU.filter((sku, index, self) =>
^^^^^^^^^^^
You should initialize product_SKU with an empty array:
data () {
return {
current_product: {product_SKU: []}, // changed here
current_ID: '',
}
}
This is needed because the computed property will be executed right away, even before your Ajax gets a chance to return.
Declare it as empty so the computed doesn't throw an error. When the Ajax fulfills, it will recompute automatically.
Even though the Ajax is started at the created(), it won't return before the computed is executed for the first time. More details about this here.

Declaring getter property when building SpyObj using jasmine.createSpyObj utility?

Let's say I have a class:
class MyRealClass {
get propOne() { return stuffFromTheServer; }
}
When testing, I want to achieve this functionality:
const mockClass = {
get propOne() { return someStuff; }
}
jasmine.spyOnProperty(mockClass, 'propOne', 'get');
By doing something like this...
const spy = jasmine.createSpyObj('mockClass', [
{methodName: 'propOne', accessType: 'get'}
]);
In other words, I want to build a SpyObj<MyRealClass> using the jasmine.createSpyObj and declare the getter properties as methods in the methodName array (the second parameter the the createSpyObj() method.
Is this possible?
createSpyObj takes an optional last parameter that lets you declare properties:
const spy = jasmine.createSpyObj(['here', 'be', 'methods'], { propOne: 'someStuff' });
or
const spy = jasmine.createSpyObj('mockClass', ['here', 'be', 'methods'], { propOne: 'someStuff' });
See here and here for the official docs
I did it surprisingly simple by this code:
const routerMock = jasmine.createSpyObj(['events']);
routerMock.events = of(new NavigationEnd(0, 'url1', 'url2'));
const serviceToTest = new SomeService(routerMock);

Watch all properties of a reactive data in Vue.js

I had an API call to the backend and based on the returned data, I set the reactive data dynamically:
let data = {
quantity: [],
tickets: []
}
api.default.fetch()
.then(function (tickets) {
data.tickets = tickets
tickets.forEach(ticket => {
data.quantity[ticket.id] = 0
})
})
Based on this flow, how can I set watcher for all reactive elements in quantity array dynamically as well?
You can create a computed property, where you can stringify the quantity array, and then set a watcher on this computed property. Code will look something like following:
computed: {
quantityString: function () {
return JSON.stringify(this.quantity)
}
}
watch: {
// whenever question changes, this function will run
quantityString: function (newQuantity) {
var newQuantity = JSON.parse(newQuantity)
//Your relevant code
}
}
Using the [] operator to change a value in an array won't let vue detect the change, use splice instead.