Why Vue .sync command not working in router view? - javascript

I'm trying to sync a variable between components using the .sync command in Vue. It works without problems when I put components in the page using the tag (for example: <my-component></my-component>). When I bind it in a <router-view>, it works only one-way. Is it normal?
When I click on the link inside the component, it does not change the value of test in the root Vue object. When I change it in the root object, the component inherits the value correctly.
Click here for an example

You are trying to update the prop directly, the correcto way to update it is to emit an update. Remember :test.sync is a shorthand to v-bind:test and v-on:update:test
On your Foo component:
editTest: function() {
this.$emit('update:test', false) // instead of this.test = false;
}
Fiddle: https://jsfiddle.net/hansfelix50/u7k5qpwz/

Related

Set "this" keyword of App.vue in Vuex state

I found a seloution for how to access to vue-router and other services that works only inside the vue component. In the created option of App.vue i save the "this" of vue app inside state of vuex.
does it's a good way or can make some problems in future?
instead to write:
this.$router.push('route-name')
from some component, is save the this keyword in the state as context key for example,
and now from the Actions i'm using the context instead this
such like this:
state.context.router.push('route-name')
and its works..
my question is if its good solution or not.
I think that is not a good solution, if you want to use this, you should try with the actions or getter returned value, inside a Vue file instead using it directly in an action.
I'm giving an example and an explanation
Example:
Getter:
export function getRedirect(state){
return state.routerName
}
Vue file:
<template>
Page
<button #onClick="redirect" > Redirect </button>
</template>
<script>
import {mapGetters} from 'vuex'
export default: {
computed:{
...mapGetters('VuexStoreName',['getRedirect'])
},
methods:{
redirect(){
this.$router.push(this.getRedirect)
}
}
}
</script>
So, instead of using the redirect inside an JS file, creating an action and passing this inside the parameter or getting it by state, you'll be using it correctly in a Vue file.
The probblem setting this in the state is that when it changes the instance saved will not change, and you'll have to update every time and everywhere. And calling this inside a Vue file, it'll always be updated

Putting an element inside Svelte Component

What does putting an element inside Svelte Component mean?
Eg. this code:
const target = document.createElement('div');
// render the component in the new element
const sample = new Sample({ target });
Like, here, in the given linked code, author is doing that:
https://github.com/rspieker/jest-transform-svelte/blob/master/example/test/Sample.spec.js#L8
What does this do? Is it putting Svelte component inside a div? Is it a Svelte syntax to put the element inside the constructor of the Svelte component?
Yes, that snippet is initializing the Svelte component named Sample and rendering it within the target div. The target property of a Svelte component constructor's options parameter is the only required property.
For more information, check out Svelte's components documentation.
It is the place where in your document the component will be rendered. Normally you would use a very specific location like body or a div with a certain id.
In this case however you are not actually rendering a page but merely testing a component so it doesn't matter where the div is.
You can find more info on testing with Jest here https://jestjs.io/

Vue V-Bind to Programmatically Created Instance

I follewed this instructions to create a Vue instance programmatically. I use this to dynamically add component instances in project by user events. My problem now it, that my component to initialize needs a model. I regular I would use it like this:
<my-component v-model="variable"/>
But now I create this component with this code snippet within another components methods section:
import MyComponent from '../MyComponent'
...
add () {
const Component = Vue.extend(MyComponent)
const instance = new Component()
instance.$mount()
document.getElementById('app').appendChild(instance.$el)
}
I know using a $ref here is better, but it must work globally, so I didn't know how to add it else to the DOM. But just as side note.
Now i need to give this instance a v-model binding. I already know how to define props or slots, but not a model. In the official docu they mention something for that. But to be honest I don't understand it and didn't get it work.
Can anybody tell me how I have to extend my code to define the model for this instance? Something like instance.$model = this.variable would be awesome. Thank u!
Finally I got some kind of workaround for this. I'm not aware if there is a better solution out there, but this works for me.
The MyComponent used this description to handle the v-model. By this is emit the change event for the parent component. So The idea is simply to pass the model variable as property, work in MyComponent on a copy of this variable and emit changes to the parent. To catch this change event I can add to my instance the following:
const Component = Vue.extend(EditWindow)
const instance = new Component({
propsData: { content: this.variable }
})
instance.$on('change', value => {
this.variable = value
})
instance.$mount()
document.getElementById('app').appendChild(instance.$el)
I guess this is pretty the same as Vue actually does in the background (maybe?). But after all it works and I'm happy. Of cause I'm open for the 'correct' solution, if such one should exist.

How to access Child component state and lifecycle methods and validate in React with Jest+Enzyme?

Need help with enzyme for testing. I have checked here but it did not help: How does one access state on a nested React component wrapped by an HOC?
Here is my problem:
How can I check function called or not and state of Child component? I also need to check lifecycle, so I used mount of parent component, but haven't done that yet.
I used below when I rendered one component:
expect(searchWrapper.find('select [selected]').val()).to.equal('someId'),
but with mount, this is not working, as it complains searchWrapper.find(...).val is not a function which I believe is a cheer IO and it worked with render only. So what will be the proper way for me?
What I intend to do: On child select change, check (and/or match):
child func is called once
parent func is called once (called inside 1.)
parent state
child state
lifecyle methods like componentWillReceiveProps and componentDidMount etc
Result rendered output validation, also including some of the above.
Component is like
class ParentWrapper {
// state and other functions and lifecycle methods
render(){
....
<SearchWrapper {...props}/>
<ResultWrapper {...props}/>
}
}
class SearchWrapper {
// state
// lifecycle methods
// functions
}
and same for ResultWrapper.
Summarizing it again with some code:
I want to access state and other objects of Child node, just like we can do with root. Also access rendered objects like selected option from the select menu, for example.
// state is not a function, as it has to be called for root only, then whats the alternative
expect(parentWrapper.find(SearchWrapper).state().searchId).to.equal('someValue');
// Below also did not work, it worked when I tested SearchWrapper individually using render()
// which is a CheerIO function, but I need to use mount of parent for whole component testing
// and inter-component interactions
searchWrapper.find('.form1 select').simulate('change', {target : {value : 'someValue'}});
// sinon spy on change is triggered
expect(searchWrapper.render().find('select [selected]').val()).to.equal('someValue');
// AssertionError: expected undefined to equal 'someValue'

Is my React component being recreated instead of updating?

I am trying to combine Angular and React.js. I have an work example project here I have seen a couple of ways to bring the Angular and React.js together. One of the methods I have seen is to create a directive and create the React component in the link function. For example in the first part of the project to generate the React version(in red) I am using
.directive('reactElementRepeater', function() {
return {
link: function(scope, element) {
var update_react = function(oldVal, newVal){ //Called every time one of the two values change
React.renderComponent(Demo_Element({
numberOfElements: scope.myModel.numberOfElem,
numberInElements: scope.myModel.numberInElem
}), element[0]);
}
scope.$watch('myModel.numberOfElem.length', update_react);
scope.$watch('myModel.numberInElem', update_react);
}
}
});
What I want and what should happen in a React enabled application is for something in the model to be updated, then that update is sent through React and it will alter the DOM as little as possible to reflect that change. It looks like that instead of updating a bit of the DOM this will Create a new React component each time with renderComponent.
React.renderComponent() instantiates the root component, starts the
framework, and injects the markup into a raw DOM element, provided as
the second argument.
Is it actually recreating the elements each time? If that is the case is there a way to alter this so that doesn't happen?
Just to be clear I know about ngReact, I just want to know other ways to speed up Angular with React.
Yes this is fine, it's not mounting the component multiple times.
When you call React.renderComponent() the second argument is the element which react should render the component to. So react notices if you are rendering the same component to a dom element that already contains a mounted instance of the component, and does not re-mount the entire component, it just updates the properties of it instead.
You can see this in action if you make a component with componentDidMount function defined. You'll notice that componentDidMount will only execute the first time renderComponent gets called. And afterwards, subsequent calls to renderComponent on the same target dom element will not call it because the component is already mounted. Likewise getDefaultState and getDefaultProps also only get called on the first renderComponent call.
If you're asking will the render function of the component be called every time the answer is yes. But this is how react works, you want the render function to get called because props might have changed. You can block it from being called by using shouldComponentUpdate (http://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate) and returning false. However react developers recommend you don't use this to block render calls unless you have specific performance problems - most of the time it should be fine to just let the render call execute as it wont cause any slow dom updates unless things have actually changed.

Categories