How to pass variable data between components in Vue js - javascript

Here I'm trying to pass the variable header_url data to my other vue pages. Since I also want to use this for push and post methods in the other vue script tags. I'm not sure how to do it? Since, I can only find examples with data been transferred between html tags.
// Home.vue
<template>
<div>
Home
<h2>logout</h2>
<a v-bind:href="url">logout</a>
</div>
</template>
<script>
export default {
data: () => ({
url:"https:..."
})
}
var header_url = window.location.href;
if (header_url.length>100) {
var token=window.location.href.match(/\#(?:id_token)\=([\S\s]*?)\&/)[1]; // eslint-disable-line
console.log(token);
}
</script>

To pass data between two URLs in single page app, you need use Vue Router
and Route Meta Fields.
From the docs :
Sometimes, you might want to attach arbitrary information to routes like transition names, who can access the route, etc. This can be achieved through the meta property which accepts an object of properties and can be accessed on the route location and navigation guards

Related

Data from store not reactive in Vue.js 3

This is my first attempt at building a web app with Vuejs. I've been trying to get data from an external JSON API and display it on my app. The JSON fetch etc is working fine. but I can't get the data to be displayed reactively on my component.
As you can read in Appraisal.js given an API link some data is populated in Appraisal.app_data. The data always has an array called items (that's just how the API is. I'll add validation later). As a proof of concept I'm trying to display the number of elements in the items array.
Since other components in my app will also use this data, I'm using an external store as the data source everywhere. One of the components calls Appraisal.setLink() on getting some user input. That part is working as expected. However the DOM contents don't change at all.
I referred to State Management for setting up the external store. I also referred to some other answers on StackOverflow with a similar issue and got the following suggestions:
The data should be initialized to undefined or null instead of {} for reactivity to work.
Properties of objects are not reactive. But by my understanding this was changed in Vue3 where it doesn't matter because proxies are in use. Either way I tried using the Object.assign({}, ..., ...) method but it did not help.
Arrow functions cannot be used in methods for reactive objects. If I remove the arrow function and put the body inside .then(function(data) {...}) it complains that this is not defined for the second then function on fetch
// --- src/components/AppraisalView.vue
<script setup>
import ItemView from './ItemView.vue';
</script>
<template>
<div v-if="app_data">{{app_data.items.length}} items in appraisal</div>
<div v-else>Enter link to get quote</div>
</template>
<script>
import {Appraisal} from '../stores/Appraisal.js';
export default {
data() {
return {
app_data: Appraisal.app_data,
}
},
}
</script>
// ---- src/store/Appraisal.js
import {reactive} from 'vue'
import {BuybackCalculator} from './BuybackCalculator.js';
export const Appraisal = reactive({
link: '',
app_data: undefined,
methods: {
setLink(value) {
if (this.link == value) return;
this.link = value;
console.log('Updating appraisal with: '+this.link);
fetch(this.link+".json")
.then((response) => response.json())
.then((data) => {
this.app_data = data;
console.log(this.app_data);
BuybackCalculator.methods.calculate_buyback(this.app_data);
});
}
}
});

How to share variables between functions in Vue

I'm learning Vue and trying to test out how I'd pass a user input from one function to another.
My use case is this. I want to take a users input, store it and then supply that to a second function as a variable that it can use to make an API call.
In isolation the two code sections are:
User Input
<div id="v-model-basic" class="demo">
<input v-model="message" placeholder="edit me" />
<p>Message is: {{ message }}</p>
</div>
Vue.createApp({
data() {
return {
message: ''
}
}
}).mount('#v-model-basic')
API Call
import axios from 'axios';
/* API call for the weather data */
export default {
name: "Weather",
data() {
return {
weatherList: []
};
},
methods: {
getweatherData() {
axios.get("https://anAPIpath.com/that-I-want-to-add-user-input-to").then(response => (this.weatherList = response.data));
}
}
};
Is there a way to do this in Vue where they are both methods within that export function, or is that just the wrong approach? As mentioned, new and learning Vue and I want to ensure I approach this the "Vue way" so things are as neat and tidy as possible.
Vue has several options for passing variables between components.
props
You can make the variable a prop of the other:
props: {
message: String
}
The prop is accessed with this.message but it is recommended you copy it to a variable in data and reflect changes with $emit (see documentation link, and $emit section below).
See documentation: https://v3.vuejs.org/guide/component-props.html#props
$emit
You can let a parent component know about the other component's changes with $emit. You can just name an event yourself and pass the value as the first parameter.
this.$emit('messageUpdate', this.message);
See documentation: https://v3-migration.vuejs.org/breaking-changes/emits-option.html#emits-option
VueX
With the VueX data storage you can transfer variables from any component across your app to any other.
This takes a little more finess to set up. I suggest going with the above first.
If you are interested (definitely worth to learn), here is the link:
https://vuex.vuejs.org/guide/#getting-started
I see you are doing well, you just need to add the API call to a script tag in the same file and then access the input message like this:
axios.get("https://anAPIpath.com/"+ this.message)

Nextjs - first level dynamic route

I want to have user profiles in my app at domain.com/:username .How do I do it? creating a new folder in /pages will create a new URL section like /user/:username which I don't want.
Just name your file inside pages as [username].js
Creating a dynamic route
You can create a dynamic route by putting the filename in brackets. For instance:
pages/[id].js
pages/[slug].js
pages/posts/[slug].js
pages/[author]/[slug].js
pages/[author]/bio.js
Notice how the dynamic route can be at any level. It doesn't simply need to be at the root of the pages folder, and it doesn't need to be the last level of the url either. Also notice that you can name the dynamic route anything you want. You're not restricted to just using [id] or [slug].
In your case, use pages/[username].js
Accessing the route name
If you create a dynamic route at pages/posts/[slug].js, any page at https://example.com/posts/slug-of-the-post will lead to that page. However, you likely want different content on each page (i.e., that the user is on https://example.com/posts/slug-of-the-post, not https://example.com/posts/slug-of-a-different-post. For this, you need to access the contents of the route.
Inside the page
You can use the router to get the name of the route.
// pages/posts/[slug].js
import { router } from 'next/router'
export default function PostPage() {
const router = useRouter()
const slug = router.query.slug // "slug" because that was the name of the file
return <>{/* page contents */} </>
}
So on page https://example.com/posts/slug-of-the-post, the variable slug will be slug-of-the-post.
If you used [id].js, use router.query.id instead.
GetStaticProps/GetServerSideProps
Using the server-side functions, the process is very similar.
// pages/posts/[slug].js
// bottom of the file
export async function getServerSideProps(context) {
const slug = context.params.slug
return {
props: {},
}
}
Docs
By the way, I'd also recommend checking out the docs if you haven't already:
https://nextjs.org/docs/routing/dynamic-routes

Vue - How to pass data to child component after route is entered

Hey I'm relatively new to vue.js.
I have a Home.vue which creates a data array after successful login and entering the route.
I tried it with
<template>
<div class="home">
***
<History :data="this.cData" />
***
</div>
</template>
***
beforeRouteEnter(to, from, next) {
next(async (vm) => {
vm.cData = await vm.select(vm.handle);
console.log(vm.cData);
});
},
But the data is send before beforeRouteEnter() and the History component needs it for creating itself.
Is there a way do to it?
If the History component needs it for creating itself, then you should defer creation of the component (with v-if) until cData is ready. cData should be declared upfront in the data object with value null.
You're also doing this.cData in the template but it should be just cData.
<History v-if="cData" :data="cData" />

Vue js, how do I dynamically update content based on the url parameters?

I'm trying to dynamically update the content using url parameters. So I'm basically reusing the view to render content based on the url.
while that works fine for the initial load, it won't update when I'm trying to access a different link using the same view.
I've to reload the page in order for the content to update based on the new url params.
I read things and examples about using a watcher to achieve what I need, however all the examples used custom methods which I'm not interested in,
so I'm not sure how to restracture my code to work with watchers
My script looks as follows
<script>
import axios from "axios";
export default {
data() {
return {
items: [],
};
},
async created() {
const response = await axios.get("http://localhost/test/records/"+this.$route.params.dates+"/"+this.$route.params.datee);
this.items = response.data.data;
},
};
</script>
the params this.$route.params.dates and this.$route.params.datee are dates that allow me to fetch data between these two values.

Categories

Resources