0👍
You need conditional rendering. And the point is, template is not conditional, data is. So the @click
is actually always in your template, but with the data changes, you have different views, even different user interaction behaviours in your view.
-
you want a button, but only when some condition
flag
is true, so in thedata
option,flag
is false initially, but you load the real status from server via an AJAX call, which may setflag
to true so the button shows. Template may be like<button v-if="flag" @click="clicked"></button>
-
you want a button, always, but clicking it doesn’t always do something(e.g. show an alert), so you have
<button @click="clicked"></button>
, andif(this.flag) {/*do something*/}
inclicked
, whileflag
is loaded by AJAX like above.
- [Vuejs]-Express & Csurf rejects Vue (Axios) post request
- [Vuejs]-Iframe invoked with Youtube API does not appear after Vue.js V-if command
0👍
I believe I have found a good solution to my issue by using "Dynamic components" – I have built a basic example which loads in different components based on a button click, makes an AJAX call to a php script to update the alert message the new components button fires.
Here is my Code:
script.js
Vue.component('foo', {
'template' : '<button @click="aFooButton()">This is a foo button</button>',
data() {
return {
}
},
methods: {
aFooButton() {
alert(this.$parent.componentData);
}
}
})
Vue.component('bar', {
'template' : '<button @click="aBarButton()">This is a bar button</button>',
data() {
return {
}
},
methods: {
aBarButton() {
alert(this.$parent.componentData);
}
}
})
new Vue({
el : "#root",
data : {
component: null,
componentData: null
},
methods : {
makeFoo() {
axios.get('ajax/foo.php').then(response => this.componentData = response.data);
this.component = 'foo';
},
makeBar() {
axios.get('ajax/bar.php').then(response => this.componentData = response.data);
this.component = 'bar';
}
},
mounted() {
}
})
Vue.component('bar', {
'template' : '<button @click="aBarButton()">This is a bar button</button>',
data() {
return {
}
},
methods: {
aBarButton() {
alert(this.$parent.componentData);
}
}
})
new Vue({
el : "#root",
data : {
component: null,
componentData: null
},
methods : {
makeFoo() {
axios.get('ajax/foo.php').then(response => this.componentData = response.data);
this.component = 'foo';
},
makeBar() {
axios.get('ajax/bar.php').then(response => this.componentData = response.data);
this.component = 'bar';
}
},
mounted() {
}
})
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Vue</title>
</head>
<body id="app">
<div id="root" class="container">
<div>
<component :is="component"></component>
</div>
<div>
<button @click="makeFoo()">Make foo</button>
<button @click="makeBar()">Make bar</button>
</div>
</div>
<script src="ajax/javascript/vue.js"></script>
<script src="ajax/javascript/axios.js"></script>
<script src="ajax/javascript/script.js"></script>
</body>
</html>
foo.php
<?php
header('Content-Type: application/json');
echo json_encode('This is some Foo information');
?>
bar.php
<?php
header('Content-Type: application/json');
echo json_encode('This is some Bar information');
?>
This appears to me to be a good solution, can anyone tell me if there’s any reason I should not tackle my issue using this approach?
(Please note this is a basic example, I would usually have my components in separate files etc)
Thanks in advance
EDIT:
Reading further I have discovered "Vue Router" which seems to offer a similar solution to what I have achieved above – Does anyone have any experience with this and is it a better option?
EDIT 2:
I decided to recreate the above using Vue Router, the code for anyone interested is:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Vue</title>
</head>
<body id="app">
<div id="root" class="container">
<div>
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</div>
<div>
<router-view></router-view>
</div>
</div>
<script src="router/javascript/vue.js"></script>
<script src="router/javascript/router.js"></script>
<script src="router/javascript/axios.js"></script>
<script src="router/javascript/script.js"></script>
</body>
</html>
script.js
const Foo = Vue.component('foo', {
'template' : '<button @click="aFooButton()">This is a foo button</button>',
data() {
return {
loading: false,
message: null,
error: null
}
},
created () {
// fetch the data when the view is created and the data is
// already being observed
this.fetchData()
},
watch: {
// call again the method if the route changes
'$route': 'fetchData'
},
methods: {
fetchData () {
this.error = this.post = null
this.loading = true
axios.get('async-ajax/foo.php').then((response) => {
this.message = response.data;
});
},
aFooButton() {
alert(this.message);
}
}
})
const Bar = Vue.component('bar', {
'template' : '<button @click="aBarButton()">This is a bar button</button>',
data() {
return {
loading: false,
message: null,
error: null
}
},
created () {
// fetch the data when the view is created and the data is
// already being observed
this.fetchData()
},
watch: {
// call again the method if the route changes
'$route': 'fetchData'
},
methods: {
fetchData () {
this.error = this.post = null
this.loading = true
axios.get('async-ajax/bar.php').then((response) => {
this.message = response.data;
});
},
aBarButton() {
alert(this.message);
}
}
})
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
const router = new VueRouter({
routes: routes
})
new Vue({
el : "#root",
router: router,
})
In my experience Vue Router is better for single page applications, it updates the URL in your browser etc where as I feel Dynamic Components suits my personal needs more. I’d be interested to hear other peoples opinions and experiences.
- [Vuejs]-Accessing object properties in Vue after loading in Sails app
- [Vuejs]-VueJS SPA freezing\lagging