How to get same Vue components from page by some attribute - vue.js

I want to get from an Accordion vue component all others Accordion components on the page with the same props or data value.
I've tried a method this.$parent.$children, but it will not working if components are in different wrappers.
let state = this.active;
this.$parent.$children.forEach(value => {
if (value.commonCssClass === this.cssClass)
value.active = false;
});
this.active = !state;

How about register components that you need in lifecycle methods?
in beforeMount register that component in global object
and beforeDestroy to un-register it

A way to solve my problem.
beforeMount() {
if(!window.VueAccordeons)
window.VueAccordeons = {};
if(!window.VueAccordeons[this.cssClass])
window.VueAccordeons[this.cssClass] = [];
window.VueAccordeons[this.cssClass].push(this);
},
beforeDestroy() {
if(window.VueAccordeons)
delete window.VueAccordeons;
},

Related

Echarts OnClick Methods not reaching external methods in Vue

So I have implemented Echarts with a Vue application, on one of the charts, I am trying to get the item clicked and pass it back to the parent component that way I can do specific calculations to it.
The 'on click' method works and I can console.log('params') easily, however, trying to reach any other functions outside of it is not possible for some reason...
here is my code...
data() {
return {
myChart: null,
selectedState: {}
}
}.
mounted() {
this.myChart = echarts.init(document.getElementById("geoMap"))
this.myChart.on('click', function(params){
// It will run the console.log with correct info, but the
// method is not reachable...
console.log(params)
this.setSelectedState(params)
})
},
// Inside my vue script this is just a method to set the data for now...
methods: {
setSelectedState(params){
this.selectedState = params
},
}
any help would be nice!! thanks!
You're not in the Vue component context when listening to the chart event, so you have to change your callback function to an arrow one to access the component's this :
this.myChart.on('click', params => {
this.setSelectedState(params)
});
methods: {
setSelectedState(params) {
console.log(params);
this.selectedState = params
}
}
By the way, you should use ref instead of getting your div with document.getElementById to attach your chart :
<div ref="geoMap"></div>
this.myChart = echarts.init(this.$refs.geoMap);

Is there a way to access Vue $scopedSlot's mounted DOM element?

I have a scoped slot named myElement, I can access it via this.$scopedSlots.myElement()[0].
Usually when a vnode is mounted there is a $el containing the DOM element, but not in scoped slots apparently, there is only an undefined elm.
I also tried to put a ref on the slot in the child template and access it through .context.$refs but it lists the refs on the parent template only.
Is there any way I can access that mounted DOM element, if its id or class is unknown from the child component?
Thanks
More Details:
Parent template (Pug)
child-component
template(v-slot:myelement="{ on }")
span My element content
Child component
mounted () {
console.log(this.$scopedSlots.myelement()[0])
// From here I want to get the position of the span with
// span.getBoundingClientRect()
}
Reproduction link:
https://codepen.io/antoniandre/pen/BaogjrM?editable=true&editors=101
So something like this can be used to workaround:
mounted () {
const myEl = this.$scopedSlots.myelement()[0];
if(myEl.data && myEl.data.attrs && myEl.data.attrs.id){
const id = myEl.data.attrs.id
console.log([this.$el.querySelector('#id')])
} else {
throw new Error('slot myelement needs an id');
}
}
or forcefully apply an id:
const Child = {
render: function(h){
const myEl = this.$scopedSlots.myelement()[0]
myEl.data = {attrs: {id: 'id'}};
console.log(myEl)
return h('div', {}, [myEl])
},
mounted () {
console.log([this.$el.querySelector('#id')])
}
}
The only workaround that I've found so far is this:
First get the vnode of the scopedSlot, get its given context, crawl each vnode children of the context to find itself by the _uid key, which will contain the $el mounted element.
This is not very straightforward but it does the trick.
mounted () {
const { context } = this.$scopedSlots.activator()[0]
console.log(context.$children.find(vnode => vnode._uid === this._uid).$el)
}
I asked in Vue forum and Vue chat but I am still looking for a better way, if there is let me know.

dynamic templating - props for child component should be reactive but are not

I started Vue.js two days ago and I already need your help.
I have a state machine component which renders a child component passed as parameter. Because I do not know in advance which component I am going to display and the props it takes, I am using render functions instead of templates for the state machine parent component.
Code excerpt goes like this :
function render(h) {
const app = this;
props.reduce((acc, key) => ((acc[key] = app[key]), acc), currentPropsObj);
console.log("child props", currentPropsObj);
return app.hasStarted
? h(
renderComponent,
{
// copy the props from the machine vue component to the render component
props: Object.assign({}, currentPropsObj)
},
[]
)
: h("div", {}, "LoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLoLo");
}
return Vue.component(name, {
render,
data: function() {
return initialData;
},
methods: {
set: function(stateObj) {
Object.keys(stateObj).forEach(key => (this[key] = stateObj[key]));
}
},
The issue is that the dynamic renderComponent does not seem to take into account the props it (should) receives as parameter. I checked that currentPropsObj is correctly computed. Using Vue devtool, I also checked that the Search child component (the one I am using in the demo) props are not udpated when its parent data is updated.
For a full demo and reproduction, I made a codesandbox : https://codesandbox.io/s/m5jzqw9w3y
What can I be doing wrong?

Vue.js: instantiate functional component programmatically

when I instantiate functional component using this code
const Component_Constructor = Vue.extend(Component);
let component_instance = new Component_Constructor();
component_instance.$mount();
the component gets undefined context argument on the render function
how can i pass parameters (props, slots, children, ...) to the component?
the only workaround I found so far is to wrap the functional component into another normal component like this:
let AComponent = {
functional: true,
name: 'a-component',
render(h, context) {
return h('div', context.children[0].text);
}
};
let template = `<a-component>test content</a-component>`;
let WrapperComponent = Vue.extend({
components: {AComponent},
template,
});
let componentInstance = new WrapperComponent().$mount();
let content = componentInstance.$el;
As one of the vuejs core team said here https://forum.vuejs.org/t/functional-component-with-vue-extend/40752, you can not mount functional component manually.
$mount() need a vue instance, that a functional component does not have.

VueJS 2 $emit and $on

I use VueJS 2 and I really don't figure out how communicate from child component to parent.
I have 2 components : Dashboad and DashboardPanel.
In DashboardPanel, I have one method :
execute () {
// emit to parent
this.$emit('executeSQL', this.value)
...
}
And in Dashboard :
mounted () {
// get event from DashboardPanel
this.$on('executeSQL', function(value) {
alert(value)
})
}
Nothing happens, I don't find in doc where to use $on and I don't know if I can use other way to achieve it ?
You have to specify in Dashboard component how to react to executeSQL event from DashboardPanel component. In the HTML template of Dashboard:
<DashboardPanel v-on:executeSQL="doExecuteSQL($event)" />
doExecuteSQL beeing a method of Dashboard:
methods: {
doExecuteSQL(value) { ... }
}
Hope this will help.