Vuejs not passing property to mounted - html

Have the following code:
export default new Router({
routes: [
{
path: '/noticia/:id',
name: 'Noticia',
component: Noticia,
props: true
}
]
})
export default {
name: 'Noticia',
data () {
return {}
},
props: ['id'],
computed: {
noticia () {
return this.$store.getters.noticia
}
},
mounted: function () {
this.$nextTick(function () {
console.log(id)
// Code that will run only after the
// entire view has been rendered
})
}
}
<div>{{id}}</div>
The problem is {{id}} is showed by html div, but it isn't passed to 'mounted', so, i cannot run my 'console.log(id)' (as it will run a code to bring data and put it into the computed).
I have other code running with the same data, running wheel, cannot understand the error

mounted() {
console.log( this.id )
}

To get it working on mounted, just did:
this.id instead of just id

Related

How to properly handle a prop change with a LitElement component?

My scenario:
I have a web component created with LitElement which has an object property.
In order to initialise it, i am waiting for the element to get created:
<script>
document.addEventListener("DOMContentLoaded", () => {
const instance = document.querySelector("#myInstance");
instance.config = {
data: [
{ firstName: "John", lastName: "Doe", age: 32 },
{ firstName: "Jane", lastName: "Boe", age: 30 },
]
};
});
</script>
<my-component id="myInstance"></my-component>
Let's say that i am going to change this data prop from time to time.
I would like to check the value of the data once it is changed and then decide what i should do next. In order to do that, this is the code of my web component:
#customElement("my-component")
export class MyComponent extends LitElement {
#property({ type: Object }) data: Object;
protected updated(_changedProperties: Map<PropertyKey, unknown>): void {
console.log(_changedProperties);
}
render() {
return html`
<div>blabla</div>
`;
}
}
The problem is that _changedProperties map has data but it is still undefined.
What am i missing here?
changedProperties is a Map of all the property names that changed... e.g. you can use it to check what changed - if you want to access the actual value you can use the property directly.
it look like this
if (_changedProperties.has('myProperty')) {
// react to a myProperty change
console.log('The new value of myProperty is', this.myProperty);
}

react native: Not able to parse json params

I created a class to get api.
export default class ProductDetail extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
product : []
}
}
componentDidMount() {
this.getProductRequest();
}
...
then create getProductRequest function:
async getProductRequest() {
let response = await fetch('https: ...
let json = await response.json();
console.log(json);
this.setState({ product : json.data});
}
the console result is:
{id: 225782, title: "test", images: Array(1), price: "1$"}
Now in render i get same result:
render() {
console.log(this.state.product);
return (...
Now I try to read params:
render() {
console.log(this.state.product.title);
return (...
But I get this error:
TypeError: Cannot read property 'title' of underfined
what's the wrong?
Edit: Structure:
export default class ProductDetail extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
product : []
}
}
componentDidMount() {
this.getProductRequest();
}
render() {
console.log(this.state.product.title);
return (
<View> <Text style={styles.name}>title</Text></View>
);
}
async getProductRequest() {
try {
let id = this.props.navigation.state.params.productId;
let response = await
fetch('https://www.example.com/product', {
method : 'POST',
headers : {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
},
body : JSON.stringify({
id
})
});
let json = await response.json();
//json: {"data":{id: 225782, title: "test", images: Array(1), price: "1$"},"status":"success"}
this.setState({ product : json.data});
} catch(error) {
//console.log(error)
}
}
}
...
Because, componentDidMount() re-render after the first execution of rendering. So, when you are putting console.log(this.state.product.title); in the render before return, it doesn't get the title param first time.
After the re-render, the value will be available. So, if you want to check the output put console.log elsewhere or just remove it
Edit
You can call this.getProductRequest(); in componentWillMount() instead of componentDidMount()
componentWillMount() {
this.getProductRequest();
}
let product = JSON.parse(this.state.product
if(product.title){
console.log(product.title)
}
Let with above code. If you are getting string in your state, it may create an issue. Let me know if its work.
As said react official documentation :
componentDidMount() is invoked immediately after a component is mounted (inserted into the tree)
it does mean that first time your render method is unable to read the title of your product (first time that your render method is invoked, this.state.product is still an empty array). I suggest you to check if your array is empty
render() {
if (this.state.product) {
return (
<Text>Loading...</Text>
} else
return (
<View><Text>{this.state.product.title}</Text></View>
)
}
Don't use componentWillMount() because these methods are considered legacy and you should avoid them in new code.
componentWillMount()
If your render function actually does look like you posted, then this can't work. Try chaning your render function to something like this.
render() {
const { product } = this.state
if (!product || !product.title) {
return null
}
return (
<View><Textstyle={styles.name}>product.title</Text></View>
)
}

Trying to load json through Vue Axios

I'm trying to include a local JSON file from the static directory called blogs.json which has a load of blogs inside it.
I'm currently loading the blogs via Vue Axios which is a module I'm including in Nuxt JS.
Currently, the blogs are being loaded from the json file perfectly fine, however there is a noticeable few ms delay before the blogs are loaded, I'm trying to figure out a better approach to load the json file and populate the blogs array listed inside data()
This is my current code:
<script>
import PageBanner from '~/components/PageBanner';
export default {
head: {
title: 'Site Title: Blog',
meta: [
{ hid: 'description', name: 'description', content: 'Site description' }
]
},
components: {
PageBanner
},
data () {
return {
blogs: [],
isLoading: true
}
},
created () {
this.axios.get("/articles/blogs.json").then((response) => {
this.blogs = response.data
this.isLoading = false
})
}
}
</script>
This works just fine, but how could I modify this to load the json more quickly?
Just import it, do this and it should work God willing:
<template>
<div>
<!-- There should be no delay -->
{{blogs}}
</div>
<template>
<script>
import PageBanner from '~/components/PageBanner';
import blogsFromJson from '~/articles/blogs.json'; // Or wherever it is found
export default {
head: {
title: 'Site Title: Blog',
meta: [
{ hid: 'description', name: 'description', content: 'Site description' }
]
},
components: {
PageBanner
},
data () {
return {
blogs: blogsFromJson, // Just set it here
isLoading: true
}
},
/* No need for this anymore
created () {
this.axios.get("/articles/blogs.json").then((response) => {
this.blogs = response.data
this.isLoading = false
})
}
*/
}
</script>

How to let one component correspond with the other for a specific function

I've got a component where I click a color of a machine, when I change colors, the machine gets loaded with a different color inside a image carousel.
Now I also created a component in the bottom with a image gallery of the same machine. How can I make it that the image gallery also changes color when I click the color button in the top of the page?
Important notice: The two components are not in the same parent component but they do load in the same machine images already, so the methods are not wrong I believe.
this is the clickable color button:
<li
v-for="(color, index) in machine.content[0].machine_colors"
:key="color.color_slug"
v-if="color.inStock"
v-on:click="selectColor(index)"
v-bind:class="{ active: (color.color_slug === selectedColor.color_slug)}">
<img v-bind:src="color.color_dash">
</li>
this is the component that changes color:
<div class="product__carousel">
<Carousel showIcon v-if="selectedColor" :machineColor="selectedColor"/> <!-- Image carousel gets loaded in -->
</div>
and the component that needs to change color but does not:
<div id="tab-two-panel" class="panel">
<footerGallery v-if="selectedColor && machine" :machineColor="selectedColor"/>
</div>
Heres the script of the partent component:
export default {
name: 'aboutMachine',
components: {
Collapse,
footerGallery,
},
data() {
return{
selectedColor: this.getMachineColorContent(),
}
},
props: {
main: {
default () {
return {};
},
},
machine: {
default () {
return {};
},
},
},
methods: {
getMachineColorContent() {
if (this.selectedColor) {
return null;
}
return this.machine.content[0].machine_colors[0];
},
selectColor(index) {
this.selectedColor = this.machine.content[0].machine_colors[index];
},
},
}
and the component itself:
export default {
name: 'footerGallery',
props: {
showIcon: Boolean,
machineColor: {
default () {
return {};
},
},
},
data() {
return {
highLightedThumbIndex: 0,
isActive: undefined,
};
},
created() {
this.highLightedThumbIndex = this.highLightedThumbIndex || 0;
},
methods: {
selectThumb(index) {
this.highLightedThumbIndex = index;
},
},
};
This is my main.js
import Vue from 'vue';
import VueYouTubeEmbed from 'vue-youtube-embed'
import FontAwesome from './libs/fa';
import App from './App';
const eventHub = new Vue();
Vue.use(VueYouTubeEmbed);
Vue.component('font-awesome-icon', FontAwesome);
Vue.config.productionTip = false;
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>',
});
I would use events to accomplish this. The migration guide to Vue2 has a good short explanation of how to do simple event routing without using a full Vuex solution. In your case, you would declare a global event hub in one of your js files:
var eventHub = new Vue();
In your selectColor method you would emit the index selected:
selectColor(index) {
this.selectedColor = this.machine.content[0].machine_colors[index];
eventHub.$emit("select-color",index);
}
And in the footer, you would register a listener for the select-color event that calls selectThumb with the payload of the event (which is the selected index):
created() {
this.highLightedThumbIndex = this.highLightedThumbIndex || 0;
eventHub.$on("select-color",this.selectThumb);
}

ChildRoutes config not working anymore

So before this config use to work with react-router. But now I got a error message saying that; But I saw you need to use , but how to render the routes config insideReactDom.render( < div >
<Router history = {hashHistory}routes = {routes} > < /Router> </div>,
document.getElementById('react-app'));
?
routes.map is not a function
Can someone help me please.
const routes = {
component: Base,
childRoutes: [{
path: '/home',
getComponent: (location, callback) => {
if (Auth.isUserAuthenticated()) {
callback(null, Home);
} else {
callback(null, HomePage);
}
}
},
{
path: '/login',
component: LoginPage
},
]
}