Vue3 call a components method from another component - javascript

I'm trying to have a component call a function from another component but just from
inside the setup.
I've read this from vuemastery https://www.vuemastery.com/blog/understanding-vue-3-expose/
and I see that you can accomplish this like this:
methods: {
reset () {
this.$refs.counter.reset()
},
terminate () {
this.$refs.counter.terminate()
}
}
however, I don't have access to those methods inside the setup, and I also can't use this.$refs inside the setup. Is there a way I can do the same thing inside setup, or a way to access these methods inside the setup?
Those methods are undefined in setup, and I cannot access data setup from within those functions, and I cannot use $refs in setup.
The $refs is a very easy way to call a function from another component - but I can't seem to find a relatively easy way to do this with vue3 composition api - am I missing something?

Hey I figured it out https://vuejs.org/guide/essentials/template-refs.html#accessing-the-refs
If I go
<script>
export default {
setup(props) {
const counter = ref(null);
//now I have access to counter.value.reset after it's mounted
counter.value.reset(); //does not work! it's null here
onMounted(() => {
counter.value.reset(); //here it works
})
//make sure to return counter in return
looks like there is an easy way to do this in setup just has a caveat
you cant just call it right away because setup happens before mounted https://vuejs.org/guide/essentials/lifecycle.html
I am calling it on a trigger - so if someone selects something from a dropdown I am watching the v-model and am able to call it there no problem.
Thanks for all the input.
Putting this answer here in case anyone else needs to accomplish the same thing

Related

How to redefine a Class Component method in React?

I want to redefine a function/method inside a Class Component because I want to reuse it.
I tried
ClassComponent.prototype.submitForm = async () => {
...
}
but no luck.
In Jest, it is possible to do
jest.spyOn(class.prototype, 'method').mockImplementation
to change the implementation of the method. But I want to do it in React. Is there a way to do this? I need to change that method so I can fully reuse my Component. Thanks
I don't have your code to have a better context, but from what I see - you're going in a wrong direction. If you wish to overwrite the behavior of an inner-function inside the component, just overwrite it when a certain condition applies. You can check this condition in an event/hook or on init.

Use custom JavaScript code in a Vue.js app

I'm trying to insert JavaScript code in a Vue.js router app. I need to load data from the CMS the app is served from. In order to get the data from the CMS I have to use a JavaScript library from the CMS which is not made for Vue and is not exporting it's class/functions like modern JS. So I import the JS library from in the index.html by a script tag. This works as intended.
But now I have to use the class from this CMS JavaScript library.
Before writing this as a Vue-Router app I just have used Vue for templating purposes.
So I had some code packed in the window.onload event handler.
I have to create an instance for the CMS data access class.
But this leads to a build error (using vue-cli build). Since there
are no understandable error messages from the build process
I have to use trial and error. Even simple variable assignments like var a = 1 seem not to be allowed.
A console.log('something') works. But nothing else seemes to be allowed (except defining the onload-event handler)
I have added this code in a <script> Tag inside App.vue (which was created by vue-cli create)
window.onload = function() {
try {
// Instantiate class obj for CMS data access
cmsDataAccessObj = new CMSAccessData();
waitForPlayerData = true;
}
catch (e) {
console.error(e);
}
}
UPDATE
After testing the different solutions from the answers I got aware that using non-instance variables seems to cause the build errors.
This gives an error:
waitForPlayerData = true;
This works:
this.waitForPlayerData = true;
I wouldn't recommend using window.load to run your code. There are more native approaches to do this in Vue.js.
What you should do in the case you want to run it in the main component of the app before it's been loaded is to put the code inside the beforeCreate lifecycle hook of the main component.
...
beforeCreate () {
this.cmsDataLoader()
},
methods: {
cmsDataLoader () {
try {
// Instantiate class obj for CMS data access
cmsDataAccessObj = new CMSAccessData();
waitForPlayerData = true;
}
catch (e) {
console.error(e);
}
}
}
...
This will run the code everytime a component is created before the creation. You could also use the created lifecycle hook if you want to run it after the creation of the component.
Check the following link for more information about lifecycle hooks.
The best way to place JavaScript in Vue.js App is mounted function, it is called when the component is loaded:
export default {
name: "component_name",
mounted() {
let array = document.querySelectorAll('.list_item');
},
}
You don't need window.onload, you can just put whatever you want there. I'm not entirely certain when precisely in the lifecycle it renders and maybe someone can hop in and let us know but it for sure renders when page starts. (though it makes sense that it does before the lifecycle hooks even start and that it'll solve your needs)
Better & easier solution if you want to load it before Vue loads is to add it to the main.js file. You have full control there and you can load it before Vue initializes.
No need for window.onload there either, just put it before or import a JS file before you initialize Vue, because it's going to be initialized by order.

How to return value into the script of another Vue file? Or how to sent returned value into another Vue file?

In the main page, I got the value I want which are "time" and "breedKey" already. Now, how can I use them in another Vue file like the example I provide next
data() {
return {
time:[]
}
},
computed: {
breedKey() {
return this.breeds[this.currentBreed].key;
}
}
This is the child page <script> that I want to pass my data(breedKey, time) into, I want to use the parameters like this. Not quite sure if the logic is too simple, or are there any better method to do it?
async created() {
try {
this.promise = axios.get(
"https://my-api/"
);
You could pass them from parent to child using props.
If you have to navigate you could use vue-router and pass them as parts of the route and then retrieve them in the second page
If you want an even more decoupled way of communicating you could use EventBus or go all the way an use Vuex.
Most likely you just need to pass them as props, so declare a child that has the props declared
export default {
props:['breedKey', 'time']
}
and then pass them
<ChildComp :breedKey="breedKey" />
You can use global variable even tough this is not the main purpose of it in your case.
You define it somewhere with Vue.prototype.$myvar
And you can use it in your component like this.$myvar
However you should probably have a look at Vuex and the concept of store.

Find and manipulate a React.js component from the JavaScript console

When I work with JS I tend to whip out a console for the browser and manipulate values on the fly.
I have a page where I use React to render some components and I had the idea that it would be great to be able to manipulate it's state from the console to debug a design quirk which is only visible if the component is in a corner-case state.
I ran into problem that I was unable to get hold of a reference to my component.
I figured there might be a list of active components currently being rendered somewhere, but I was not able to find one on the React global object or anywhere else.
Is there an exposed reference to the components being rendered?
I'm rendering the component like:
<script>React.render(React.createElement(Comp, domElem))</script>
I could store a reference to the result of React.createElement() but it seems to be an antipattern. Also I'm using the ReactJS.NET library to handle server-side rendering for me so the whole React.render line is generated and is hard to modify.
My other idea was to create a mixin that makes the component explicitly expose itself on mount, like:
var ActiveComponents = [];
var debugMixin = {
componentDidMount: function () {
var id = this.getDOMNode().id;
ActiveComponents[id] = {
id: id,
getState: () => { return this.state; },
setState: (state) => { this.setState(state); },
comp: this
};
}
};
Are there drawbacks for an approach like this? Is this the same antipattern mentioned above?
Although being much cleaner than entangling these test hooks in the component code directly, adding a mixin is still a modification, and I would like to avoid that if possible.
The questions I hope to get answers for are bolded.
A workaround for this is to assign your object to the window object:
window.myStateObject = myStateObject
and then you can inspect it in the console:
window.myStateObject
There is a ReactJS extension for Chrome that may meet your needs https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi
If that isn't good enough, React keeps track of all the mounted components in a private variable instancesByReactID. If you just want to access these for debugging, you could modify the React code and expose that variable as a global.

this.setState is not a function, react native

I am aware there are similar issues but none of them helped me to fix mine.
So here is my issue.
I am working with react native and using the flux dispatcher. Dispatch and register of my app dispatcher works fine. My issue is that when I want to change/set the state inside the dispatch register function I always get the error message that this.setState() is not a function. Of course I thought this must be a binding issue then (writing in es6), so I tried all sorts of binding "this" but I still can't get it work. Has anyone any idea why?
Here is that bit of code that doesn't work:
testDispatcher() {
AppDispatcher.register( (action) => {
if ( action.action === TEST_ACTION ) {
// I tried setting state inside here
this.setState({
view: action.view
}).bind(this); // with or without this bind doesn't make a difference
// I also tried having a function outside of this function where I set the state.. this doesn't work either.
//this.updateView('home').bind(this);
console.log('dispatch register');
}
});
}
I also tried to console log "this" inside my register function and "this" does return my app class.
The => binds this to the scope of testDispatcher(). That's probably not what you want. In this case I think you should drop the => notation but simply a regular anonymous function.
Also, this.setState(...args...).bind(this) is totally wrong. 1) The this. part indicates that the .bind(this) is redundant. 2) The syntax for binding is like: foo.setState.bind(notFoo, ...args...).
My class didn't extend from React Component, therefore this.setState was not a function.

Categories

Resources