How to mount router-link outside app? - vue.js

I am using the basic tutorial of the guide/Getting started, but changed HTML code to
<div id="app">
<!-- ... all the same except router-view ... -->
</div>
<h2>Outside:</h2>
<code id="outApp"><router-view></router-view></code>
But, of course, it is not working, I need to say to mount router-view at #outApp, how to do it?
PS: when #outApp is inside #app all is working fine, on my page reproduction of tutorial.

As commented previously, and being sure you're already notified about this unpractical practice's. This is the solution I offer you.
Create a new Vue instance (#app2) and use the router in there.
Vue.config.productionTip = Vue.config.devtools = false // ignore
const router = new VueRouter({
routes: [
{
path: "/",
component: { template: "<router-view/>" },
children: [
{
path: "",
name: "foo",
component: { template: "<div>Foo</div>" }
},
{
path: "bar",
name: "bar",
component: { template: "<div>Bar</div>" }
}
]
}
]
});
// App1 without routing capabilities
new Vue({
// router, don't need it here
el: "#app1"
});
// App2
new Vue({
router,
el: "#app2"
});
<script src="https://unpkg.com/vue#2.5.16"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<fieldset>
<legend>App1</legend>
<div id="app1">
This is the app without router
</div>
</fieldset>
<fieldset>
<legend>App2</legend>
<div id="app2">
<router-link :to="{name:'foo'}">Foo</router-link>
<router-link :to="{name: 'bar'}">Bar</router-link>
<hr>
<router-view></router-view>
</div>
</fieldset>

Related

vue-router navigate to the same route and re-run mounted hook

How can I naviagte to the current route using router-link and re-run mounted hook?
HTML
<!-- Include the library in the page -->
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script src="https://unpkg.com/vue-router"></script>
<!-- App -->
<div id="app">
<nav>
<router-link :to="{ name: 'home' }" exact>Home</router-link>
<router-link :to="{ name: 'about' }" #click.native.prevent="router.push({ name: 'about' })">About</router-link>
</nav>
<router-view :key="$route.fullPath"></router-view>
</div>
JS
console.clear()
console.log('Yes! We are using Vue version', Vue.version)
Vue.use(VueRouter)
const Home = {
template: `<h1>Home</h1>`,
}
const About = {
template: `<h1>{{new Date()}}</h1>`,
mounted(){
console.log('mounted')
}
}
const routes = [
{ path: '/', name: 'home', component: Home },
{ path: '/about', name: 'about', component: About },
]
const router = new VueRouter({
routes,
})
// New VueJS instance
var app = new Vue({
// CSS selector of the root DOM element
el: '#app',
// Inject the router into the app
router,
})
In the above example, if I navigate to 'About' it shows the timestamp from new Date and logs 'mounted'. However, if I'm already on /about, clicking the about link does nothing. I want to re-run the whole component lifecycle when clicking 'About', even if I'm already hit it.
You'll need to change the key in the <router-view> element whenever the user clicks your about page, that will force the mounted hook:
<template>
<div id="app">
<router-link #click.native="updateViewKey" :to="{ name: 'about' }">About</router-link>
<router-view :key="viewKey"></router-view>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
viewKey: 1
};
},
methods: {
updateViewKey() {
this.viewKey+=1;
}
}
};
</script>
Try this :
router.push({
name: 'routeName',
params: {
id: 'new value'
}
})

Does vue-router works with inline-templates?

I'm trying to render multiple components that use inline-templates using vue-router but as soon as i define the inline-template the component renders no matter the url.
Does inline-templatesworks with vue-router?
It really depends on what you mean by "work". You can Frankenstein something like this and it will do what you want without throwing any errors, but I feel I'm making the world an uglier place by just posting this example:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Vue-router with inline-template</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
<router-view>
<foo inline-template id="foo"><div>foo</div></foo>
</router-view>
</div>
<script>
const Foo = { template: document.getElementById('foo').innerHTML };
const Bar = { template: '<div>bar</div>' };
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar },
];
const router = new VueRouter({
routes,
});
var app = new Vue({
el: '#app',
router,
});
</script>
</body>
</html>
This is pretty much the intro example from vuejs.org with one of the templates made into inline.
You can refer to your inline template using #
const Foo = { template: '#my-foo-template' }
const routes = [
{ path: '/foo', component: Foo },
];
<foo inline-template id="my-foo-template"> ... </foo>

vue-router doesn't recognize $ref from a component after routing

I'm new with Vuejs and vue-router I've been reading a lot View documentation and forums to figure this out.
I can make my routing working well. But I can't (easily) the "ref" from the content that was routed.
I say "easily" because I found on "this.$children[0].$children[0].$refs" which doesn't look correct to me and also difficult to maintain.
What I would like is to have easy way like "this.$refs" or "this.router["foo"].$refs".
I'll paste the vue documentation basic example with "ref" in the elements.
HTML
<div id="app">
<h1 ref="myrefInitial">Hello App!</h1>
<p>
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
<router-view></router-view>
<p>
refs founds: {{getAllRefs}}
</p>
</div>
<script src="index.js"></script>
JS
const Foo = {
template: '<div ref="myrefFoo">foo</div>'
}
const Bar = {
template: '<div ref="myrefBar">bar</div>'
}
const routes = [{
path: '/foo',
component: Foo
},
{
path: '/bar',
component: Bar
}
]
const router = new VueRouter({
routes // short for `routes: routes`
})
router.afterEach((to, from) => {
console.log("going to " + to.fullPath)
console.log(to);
router.app.getAllRefs();
})
const app = new Vue({
router,
computed: {
getAllRefs: function(){
return this.$refs
}
}
}).$mount('#app')
JsFiddle example
https://jsfiddle.net/3rdSenna/kaqqsrob/
In the end I wrote a simple For loop to dig on every $refs and find the child $refs name until is matched. It solved my problem.
But I believe the suggestion from #rinatdobr would suite me well.

Vue.js - How to capture a URL parameter as a hidden input value

I am writing a password reset function in Vue.js. As part of the process I generate a password key that is part of the reset url emailed to the user. It is very well possible that user may request a reset on one device but then go to another to do the reset. Therefore, storing it in the local storage is not an option. How to I pass the password key along with the new password. Please advise.
The way you can do this with Vue is using vue-router and accessing the $route.query object.
For instance, when the URL has ?key=somekey, the $route.query object is `{key: "somekey"}.
Here's a demo CodeSandbox showing how you could use it.
Relevant code:
// main.js
import Vue from "vue";
import VueRouter from "vue-router";
import PasswordReset from "./PasswordReset";
Vue.use(VueRouter);
var router = new VueRouter({
mode: 'history',
routes: [{
path: '/',
component: {
template: `<div>
You are at '/'.<br>
Click to simulate an external link user:
<a href="https://lrrwkyv7k7.codesandbox.io/passwordreset?key=somekey">
https://lrrwkyv7k7.codesandbox.io/passwordreset?key=somekey
</a>
</div>`
}
}, {
path: '/passwordreset',
component: PasswordReset
}]
});
new Vue({
el: "#app",
router: router,
template: '<router-view></router-view>'
});
// PasswordReset.vue
<template>
<div id="app">
<p>Hello, user.</p>
<form action="" #submit="submit">
Type some new password: <input type="text" name="newpass" v-model="newPass">
<input type="hidden" name="key" :value="hiddenKey">
<button>Send</button>
</form>
<hr>
<div class="debug">
Object that will be sent:
<pre>{{ $data }}</pre>
click here to get back to home
</div>
</div>
</template>
<script>
export default {
name: "PasswordReset",
data() {
return {
newPass: "",
hiddenKey: ""
};
},
mounted() {
this.hiddenKey = this.$route.query.key;
},
methods: {
submit(event) {
alert('We would have sent:\n'+JSON.stringify(this.$data, null, 2));
event.preventDefault(); // don't submit now, just testing...
}
}
};
</script>

how do i show content in this vue example?

I'm playing with vue for the first time and have knocked up a simple test file. I have a table that is populated by data from an api call, and have used the vue router to create links to each item but this link isn't displaying the content. the network shows it's making the request to the api, but for some reason the template is not showing (not even the hard-coded content). Why? Also, why does the route content not display on the first router view, but only the router-view in the tbl component?
<!doctype html>
<html lang="en">
<head>
<title>Vue.js test</title>
<meta charset="utf-8">
</head>
<body>
<div id="app">
<!-- this route displays correctly -->
<router-link to="/foo">Go to Foo</router-link>
<table-notification/>
<!-- content is not displayed here - why? -->
<router-view></router-view>
</div>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vue-router"></script>
<script src="axios.min.js"></script>
<script>
const foo = {template:'<div>asdfasdf</div>',};
var router = new VueRouter({
routes: [
{path: '/foo', component: foo},
{path: '/notifications/:id', component: notification_view}
]
});
var app = new Vue({
router: router
}).$mount('#app');
var notification_view = new Vue({
router: router,
template: `
<div>iop
id: {{ obj.id}}<br/>
title: {{ obj.data.title}}<br/>
message: {{obj.data.message}}<br/>
</div>
`,
data: {
obj: {},
id: 0,
},
watch: {
'$route' (to, from) {
// check for id in url
if (this.$route.params.id)
this.update_notification();
}
},
methods: {
update_notification: function(){
this.id = this.$route.params.id;
axios.get('http://api2/notifications/' + this.id)
.then(response => {this.obj = response.data.packet;});
}
}
});
var tbl = new Vue({
router:router,
el: 'table-notification',
template: `
<div>
<table>
<tr>
<th>Title</th>
<th>Created</th>
<th>Actions</th>
</tr>
<tr v-for="obj in objects">
<td><router-link :to="link(obj)">{{obj.data.title}}</router-link></td>
<td>{{obj.created}}</td>
<td>actions</td>
</tr>
</table>
<router-view/>
<!-- why must router-view be here, and why isn't notification_view showing any output?-->
</div>
`,
methods: {
link: function(obj) {return '/notifications/' + obj.id;}
},
data: {
objects: [],
},
created: function(){
axios.get('http://api2/notifications').
then(response =>
{
this.objects = response.data.packet;
});
}
});
</script>
</body>
</html>
I think you are misunderstanding the idea of Vue instances...
In you example you have:
a JSON foo that I think it is a component,
An App instance, which is mounted to the #app element
Another instance called notification_view with the same router, what I think is is another component
Another tbl instance, that I think it is another component
You actually need one instance and a bunch of components as in this example:
https://jsfiddle.net/dcr3jyzo/