Can a component be found using its key? - vue.js

Does Vue test-utils support looking for components in a list using their key? If not is there other ways of looking for components that are generated in the form of a list in vue?

You can't query a component using the key in the findComponent() method.
But you can fetch all components within your list, and then filter them like a regular array.
Just provide the right condition to find the item you want (usings its props, attrs or whatever)
const items = wrapper.findAllComponents(MyListItem)
const foundItem = items.wrappers.find(listItem => list.props('id') === 'theIdILookFor')

Related

Create component in template from data variable

I have multiple components that take same props. I want to use those components in template in such a way that I don't use multiple if-else statements in my template. I created an object in my data and paired my components with string keys. Is there a way to call those components in template with that object ? My data object looks something like this:
componentMap:{
"testComponent1":TestComponent1,
"testComponent2":TestComponent2,
},
For example, if I give "testComponent1" as key, then in template it should use TestComponent.
Use the component tag.
<component :is="componentMap['testComponent1']"></component>
See the Docs

How to programmatically expand all rows in a v-data-table component (Vuetify version 1.5)

v-data-table component has a propery "expanded" that allows to show some additional info for each row.
It works fine and I need to expand all the rows immediately when a page is loaded.
Is there a way to do that?
It is used version 1.5 of Vuetify Framework.
https://v15.vuetifyjs.com/en/components/data-tables
This is fairly easy in the new Version of Vuetify, you just use the property expanded which holds an Array of the items that are currently expanded.
<v-data-table
id="issues-table"
:value="selectedIssues"
:expanded="expandedIssues"
:items="issues"
>
<v-switch #change="(v) => expandAllIssues(items, v)" />
expandAllIssues (items, status) {
if (status) {
this.expandedIssues = items
} else {
this.expandedIssues = []
}
}
In V1.5.xx of Vuetify you don't have that luxury, but when I took a look, Vuetify works with a similar system under the hood. Firstly you should set the expand prop on the table to true, so it can expand multiple rows.
You can define a reference on your data table and then access it via this.$refs.myDataTableRef. You then realise that they store the expanded rows in an Object called expanded. You can set the rows either true by the id/name of the row in this object or you simply set the whole row objects in the vuetify expanded object to true.
I have pasted the Codepen example of their old data table and made a simple expand all button, that you can obviously change to your desires, but it should make the concept clear.
Codepen example

Connect custom element to dataset in wix & corvid

Is there a way of using a dataset query inside of a custom element. On the support page (https://support.wix.com/en/article/custom-element-faqs) its says the following:
'Can I Connect Custom Elements to Data in a Collection?
Yes, you can connect custom elements to collections using Corvid's Data and Dataset APIs.'
But I don't know how to do it. I have have tried importing wixData from wix-data at the top of my custom element however this stops my custom element from displaying.
I need to create checkboxes based on the number of items in a dataset. I have been able to create the checkboxes based on a static array in the custom element but want to do it based on the dataset so I don't have to manually keep changing the array in the custom element.
Below is what I need in my custom element.
import wixData from 'wix-data';
wixData.query('testdata')
.limit(1000)
.find()
.then(results => {
console.log(results.items)
});
You need to pass the Number of checkbox via attribute. Doc link
$w('#customElementId').setAttribute('checkboxs-count', 5 );
Then on the custom element you need to listen for the attribute change.
And update the UI based on that.
Here is a pseudo code
wixData module only exist on the Wix codebase.
You need to import the data from the database using wixDatae and pass the data to custom element via setAttribute. like this
// page code
import wixData from 'wix-data';
wixData.query('testdata')
.limit(1000)
.find()
.then(results => {
// got the data from the database now pass the data to custom element using setAttribute method
$w('#customElementId').setAttribute('checkboxs-count', results.length );
});
And You need to write the custom element code to create the checkboxes and you can listen if the checkbox change and update the database via .on() method on the custom element selector.
so, the page code should look like this.
$w('#customElementId').on('checkbox-change', (event) => {
console.log(`Checkbox Number ${event.detail.number} changed. Update Wix Database` );
});
Hope this explain how to communicate database with custom element.

possible to dynamically add objects to an array and have Vuejs detect it

edit 2
I think the issue is how I'm referring to an array from a parent component. A fiddle is provided in the comments.
I have an app where we want to be able to add items to a menu_header. I have tried pushing to the bottom of the array but Vuejs doesn't seem to be detecting it.
I have read this section https://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats and am trying to make this work but I'm not sure if this is possible.
Something like:
var obj = { name: "my name" }
menu_header.items.push(obj);
Do I need to use this.$set syntax? I really need to add into the middle of an array via splice.
edit 1
So this is a component that is recursive (ie a menu_header can have many menu_headers). I have tried adding a simple button in a menu_item to add to the parent component like this:
methods:{
addItem: function(){
var items = this.$parent.$data.menuHeader.menu_items;
var obj = { header: "my header", detail: "this detail"}
console.log("11 items length: " + items.length);
items.splice(1,0,obj);
console.log("22 items length: " + items.length);
},
The count of the number of items is incremented but the view doesn't rerender. This component is nested 3 levels deep (a Menu component has many MenuHeader components which can have many MenuItem components and also have many MenuHeader components). I'm pretty sure it's a reactivity / array issue - but not sure about exact problem.
Really the issue here was that you should use a key with a list in order for Vue to property render it in all cases and when you are iterating over a component you must use a key. The code in the fiddle is properly adding the elements to the array and Vue is detecting the changes, it just doesn't properly render the list because of it's update strategy. Using a key fixes that.
To that end I modified these lines in the template.
<div v-for="menu_header in menu.menu_headers" :key="menu_header.name">
and
<div v-for="(menu_item, idx) in menuHeader.menu_items" :key="menu_item.header">
The best key for these is some unique property of the object in the list. The above uses name and header, but I expect with real code you could come up with a better key.
It's best to get in the habit of always adding a key whenever you render a list in Vue.

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/