How to initialize component's root dom element in Vue - vuejs2

In React use of arrow function does the trick
class AppComponent extends Component {
componentDidMount() {
this.createAppComponent()
}
createAppComponent() {
const node = this.node
}
render() {
return <div ref={node => this.node = node}></div>
}
}
How can I initialize same node property in Vue component?

In Vue, you use the $el of a ref to get the underlying DOM element.
<my-widget ref='theWidget' />
mounted() {
const theElement = this.$refs.theWidget.$el
}
Other Comments
If you define the ref in a loop, 'theWidget' will be an array.
If the 'component' is just an HTML element (e.g. div or input) $el will be undefined because 'theWidget' will be the component reference.

Related

how to get data and functions of a child component from the parent component - Vue 3?

From my parent component I use a router-view to render the child views, in vue 2 use $this.refs.child... it served to access the data and functions of my view, but in Vue 3 not, how can I access this data?
In the official documentation it says that the ref can be used as follows
<script>
export default {
setup()
{
const timeLine = ref({});
const routerView = ref(null);
onMounted(() =>
{
console.log(routerView.value.timeLine)
});
return { timeLine, routerView }
}
}
</script>
And my router-view is declared like this
<router-view
ref="routerView"
class="scroll scroll-design scroll-big"
>
</router-view>
But this way it doesn't work, I don't access the timeLine property of my child component, which I have declared as follows
const timeLine = reactive(
{
show: true,
title: 'generals.evangelize',
back: 'mainHome',
width: '16.66'
});
How can I get this data from the parent component?

Render new Vue prop value [duplicate]

This question already has an answer here:
component data vs its props in vuejs
(1 answer)
Closed 1 year ago.
I have {{ story.score }} in a template and a function which updates the score:
setup(props) {
const changeScore = (value) => {
props.story.score = value;
}
return {
changeScore,
}
New value is assigned to props.story.score, but template doesn't rerender, what is missing here?
You can't change props directly in vue, it wont trigger an update. The proper way is to emit changes to parent element, like this:
setup({ props, emit }) {
const changeScore = (value) => emit('update-story-score', value);
return { changeScore }
}
Then just handle an event in parent, like this:
<template>
<Test :story="story" #update-story-score="updateStoryScore"></Test>
</template>
<script>
import { reactive } from 'vue'
export default {
setup() {
const story = reactive({ score: 1 });
const updateStoryScore = (value) => story.score = value;
return { story, updateStoryScore }
},
};
</script>
Vue props has a One-Way Data Flow
All props form a one-way-down binding between the child property and the parent one: when the parent property updates, it will flow down to the child, but not the other way around
You need to emit an event. Check out v-model on components

Call a child component method from parrent using vue / composition api

I'm trying to build a reusable modal component in Vue using this composition API. The plan is to expose a few methods like toggleModal() to call on some event in a parent component.
I've written my method in both setup() and methods.
export default {
setup() {
const isModalOpen = ref(false);
const toggleModal = () => {};
return {
toggleModal,
};
},
methods: {
toggleModalMethod() {},
},
};
If I console.log() my modal component I can see that only my toggleModalMethod() from methods is exposed.
Is there a way to expose a child method and call it from a parent component?
It's expected that a property returned from setup will be available on component instance when a child is mounted.
Here is a demo:
<template>
<div>
<Modal ref="modal"/>
<button #click="toggle">Toggle</button>
</div>
</template>
<script>
...
export default {
...
methods: {
toggle() {
this.$refs.modal.toggleModal();
}
}
};
</script>
Accessing child's members from a parent via a ref is considered an edge case, although exposing modal toggle function as public method is widely accepted scenario.

Mounting a component which is wrapped in a renderless component does not render

Let's say I have a component to get some async data:
//renderless-component
export {
render() {
return this.$scopedSlots.default({
items: this.items
})
}
}
Now I have another component, which is wrapped in this component.
//concrete-component
<template>
<renderless-component>
<div slot-scope="{items}">
//do some stuff with items
</div>
</renderless-component>
</template>
Now I want to be able to run assertions on my concrete-component:
import { mount } from '#vue/test-utils'
import ConcreteComponent from './concrete-component'
let wrapper = mount(ConcreteComponent)
When I render the mounted component, I expect the slot content to be rendered, however, wrapper.html() only returns the string <renderless-component/>, instead of the actual html.
How does one go about this?

stencil is not rerendeing component when #state() decorated property is changed

I started with stencil today. Following code is all I have in my project. Docs say, if Component member decorated with #state() is changed, component will rerender.
Any changes to a #State() property will cause the components render function to be called again.
But even this simple thing is not working. Pls advice.
import {Component, State} from '#stencil/core';
#Component({
tag: 'my-component',
styleUrl: 'my-component.css',
shadow: true
})
export class MyComponent {
#State() name:string = 'john';
changeName(){
this.name = "Peter";
console.log('inside changeName');
}
render() {
return <div>
<p>{this.name}</p>
<button onClick={this.changeName}>click</button>
</div>;
}
}
When I click on the button inside changeName is logged but no changes to name is seen in view.
Try changing your onClick to an arrow function:
<button onClick={() => this.changeName()}>click</button>
This preserves the meaning of this to reference your class. See https://stenciljs.com/docs/templating-jsx/#handling-user-input for more details and examples.
#matthewsteele answer is right but you can also define your function like below to make it work.
private changeName = () => {
this.name = "Peter";
console.log('inside changeName');
}
Doing above the this reference will still preserves to the class.