I am new to Vue.js and I know there is more than one component in a route with different names.
In App.vue file, could <router-view name="default"> be changed to other name? Thank you for your help.
HelloWorld.vue
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>Essential Links</h2>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
App.vue
<template>
<div id="app">
<!-- <img src="./assets/logo.png"> -->
<router-view name="default"></router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '#/components/HelloWorld'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})
You need dynamic components for this,
Html code
<template>
<div id="app">
<router-view :is="currentComponent"></router-view>
</div>
</template>
Js code: here depending on isTrue value set whichever component you need.
<script>
export default {
name: 'App' ,
components: {
LoginComponent,
HelloComponent
},
computed: {
currentComponent () {
return isTrue ? 'HelloComponent' : 'LoginComponent'
}
}
}
</script>
Related
i wanted to get the computed data and display in another component. However i put the computed in my app.vue and try to call this computed using :style="inputStyles" in my ChangeBackground.vue . But when i try to do this it showing error that " Property or method "inputStyles" is not defined on the instance but referenced during render" Can someone help me? Thank you
You can access the code here:
https://codesandbox.io/s/hardcore-morning-5ch1u?file=/src/components
Here is the code:
App.vue
<template>
<div id="app">
<ChangeBackground msg="Hello Vue in CodeSandbox!" />
</div>
</template>
<script>
import ChangeBackground from "./components/ChangeBackground";
export default {
name: "App",
components: {
ChangeBackground,
},
data() {
return {
bgColor: "red",
};
},
created() {
this.bgColor = "#F6780D";
},
computed: {
inputStyles() {
return {
background: this.bgColor,
};
},
},
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
body {
background-color: blue;
}
</style>
ChangeBackground.vue
<template>
<div class="hello" :style="inputStyles">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
msg: "Getting the computed area here to change the background",
};
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
h1,
h2 {
font-weight: bold;
}
ul {
list-style-type: none;
padding: 1rem;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
You should pass it as prop as you did with msg :
App.vue
<ChangeBackground msg="Hello Vue in CodeSandbox!" :input-styles="inputStyles" />
ChangeBackground.vue
<template>
<div class="hello" :style="inputStyles">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props:["inputStyles"],//⬅
data() {
return {
msg: "Getting the computed area here to change the background",
};
},
};
</script>
I know basics of html, css and js. I have just started learning Vue.js. There is a Home Page in my Vue JS Application which has two buttons. On Click of that button, navigation should happen. (New Component to be loaded). But, in the current code, on button click, navigation is not happening. Please Assist. Copying few file as seen below.
App.vue
<template>
<h3> Home </h3>
<button #click="goToCreate()"> Create Package </button>
<br><br>
<button #click="goToEdit()"> Update Package </button>
</template>
<script>
export default {
name: 'App',
components: {
},
methods:{
goToCreate(){
this.$router.push('/createpackage');
},
goToEdit(){
this.$router.push('/updatepackage');
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
main.js
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import App from './App.vue'
import CreatePackage from './components/CreatePackage.vue'
import SearchAndUpdatePackage from './components/SearchAndUpdatePackage.vue'
const router = createRouter({
history: createWebHistory(),
routes:[
{
path : '/createpackage',
component:CreatePackage
},{
path : '/updatepackage',
component:SearchAndUpdatePackage
}
]
})
const app= createApp(App);
app.use(router).mount('#app')
config.js
let baseUrl = ''
if (process.env.NODE_ENV === 'production') {
baseUrl = 'http://yourdomain.com/api/'
}
else {
baseUrl = 'http://localhost:9000/'
}
export const apiHost = baseUrl
CreatePackage.vue
<template>
<div>
<form name="createPackageForm" #submit="submitNewPackage" method="post">
<input type="number" name="noOfPostpaid" placeholder="PostPaid" v-model="posts.noOfPostpaid">
<br> <br> <br>
<input type="number" name="noOfPrepaid" placeholder="PrePaid" v-model="posts.noOfPrepaid">
<br> <br> <br>
<button>Submit</button>
</form>
</div>
</template>
<script>
import { apiHost } from '../config'
import axios from 'axios'
export default {
name:"CreatePackage",
data(){
return{
posts: {
noOfPostpaid:null,
noOfPrepaid:null
}
}
},
methods:{
submitNewPackage(e){
console.warn(apiHost+'tdg/createpackage/'+this.posts.noOfPostpaid+'/'+this.posts.noOfPrepaid);
e.preventDefault();
axios.post(apiHost+'tdg/createpackage/'+this.posts.noOfPostpaid+'/'+this.posts.noOfPrepaid,{
headers: {
"Access-Control-Allow-Origin": "*"
}},null).then(
response => {
console.log(response.data)}
).catch(e => {
console.log(e);
})
this.posts.noOfPostpaid='';
this.posts.noOfPrepaid='';
}
}
}
</script>
SearchAndUpdatePackage.vue
<template>
<div>
<input type="search" name="accountUUID" placeholder="Account UUID" v-model="posts.accountUUID">
<br> <br> <br>
<button #click="searchAccountUUID">Search </button>
<br> <br> <br>
<textarea id="myTextArea" cols=100 rows=20 v-model="posts.responseJSON"></textarea>
</div>
</template>
<script>
import { apiHost } from '../config'
export default {
name:"SearchAndUpdatePackage",
data(){
return{
posts: {
accountUUID:null,
responseJSON:null
},
}
},
methods:{
searchAccountUUID(e){
const url=apiHost+'tdg/carbon/'+this.posts.accountUUID;
console.log(url);
e.preventDefault();
fetch(url).then(response => response.json())
.then(data=>this.posts.responseJSON=JSON.stringify(data,null,4))
.catch(e => {
console.log(e);
})
console.log(this.posts.responseJSON);
}
}
}
</script>
With Vue-Router, you need to use the router-view component. When you navigate to a URL defined in your routes config, Vue-Router will match that URL and display the associated component.
It's common to place it in App.vue:
<template>
<h3> Home </h3>
<button #click="goToCreate()"> Create Package </button>
<br><br>
<button #click="goToEdit()"> Update Package </button>
<router-view />
</template>
<script>
export default {
name: 'App',
methods: {
goToCreate() {
this.$router.push('/createpackage');
},
goToEdit() {
this.$router.push('/updatepackage');
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
You might have an issue with it being a direct descendent of <template>, but I'm not sure.
This question already has answers here:
Vue 2 - Mutating props vue-warn
(28 answers)
Closed 2 years ago.
I have 3 .vue here: App.vue (default), Todos.vue and Todoitem.vue. I am following the tutorial from https://www.youtube.com/watch?v=Wy9q22isx3U&t=2458. May I know why the author in TodoItem.vue emit id two level up to App.vue to perform the method to delete? Is it best practice or better coding style? Is it easier to just go up one level for Todos.vue to do the same? Below is my one level up approach for any comment.
Below is my TodoItem.vue code
<template>
<div class="todo-item" v-bind:class="{'is-complete':todoObj.completed}">
<p>
<input type="checkbox" v-on:change="markComplete" />
{{todoObj.title}}
<button #click="$emit('del-todo',todoObj.id)" class="del">x</button>
</p>
</div>
</template>
<script>
export default {
name: "TodoItem",
props: ["todoObj"], // todoObj is defined in the parent.
methods: {
markComplete() {
this.todoObj.completed = !this.todoObj.completed;
}
}
};
</script>
<style scoped>
.todo-item {
background: #f4f4f4;
padding: 10px;
border-bottom: 1px #ccc dotted;
}
.is-complete {
text-decoration: line-through;
}
.del {
background: #ff0000;
color: #fff;
border: none;
padding: 5px 9px;
border-radius: 50%;
cursor: pointer;
float: right;
}
</style>
Below is my Todo.vue code
<template>
<div>
<h1>Todo List2</h1>
<!-- :key= and v-bind:key= are exactly the same. -->
<!-- v-bind. Shorthand: : -->
<div v-for="todo in ptodos" :key="todo.id">
<!-- Define todoObj here which to be used in the child component, TodoItem -->
<MyTodoItem v-bind:todoObj="todo" v-on:del-todo="deleteTodo" />
<!-- del-todo is from the child. child goes up to parent and then to grandparent (App.vue) -->
</div>
</div>
</template>
<script>
import MyTodoItem from "./TodoItem.vue";
export default {
name: "Todos",
components: {
MyTodoItem
},
props: ["ptodos"],
methods: {
deleteTodo(id) {
this.ptodos = this.ptodos.filter(todo => todo.id !== id);
}
}
};
</script>
<style scoped>
</style>
Below is my App.vue code
<template>
<MyToDos v-bind:ptodos="todos" />
</template>
<script>
import MyToDos from "./components/Todos";
export default {
name: "App",
components: { MyToDos },
data() {
return {
todos: [
{
id: 1,
title: "Todo One",
completed: false
},
{
id: 2,
title: "Todo Two",
completed: true
},
{
id: 3,
title: "Todo Three",
completed: false
}
]
};
}
};
</script>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: Arial, Helvetica, sans-serif;
line-height: 1.4;
}
</style>
If you can do it with one level up it's better. To have multiple props on each child can be a bad practice called prop drilling.
Vuex is a good alternative to avoid to get props nested.
I have a variable in my parent component and would like it to be sent to the child component.
I tried several ways but nothing works on my side, here is my code:
Parent :
<template>
<Widget/>
</template>
<script>
import Widget from './Widget'
export default {
data () {
return {
model: {
data: 'data send !'
}
}
},
components: {
Widget
},
methods: {
}
}
</script>
Child :
<template>
<div class="row">
<div class="box">
<p> {{data}} </p>
</div>
</div>
</template>
<script>
export default {
data () {
return {
data: '111'
}
}
}
</script>
<style scoped>
.box {
box-shadow: 10px 10px 5px grey;
}
</style>
thank you in advance for your help!
To bind data to a child component you can use props.
Parent :
<template>
<Widget :data="model.data"/>
</template>
<script>
import Widget from "./Widget";
export default {
data() {
return {
model: {
data: "data send !"
}
};
},
components: {
Widget
},
methods: {}
};
</script>
Child:
<template>
<div class="row">
<div class="box">
<p>{{data}}</p>
</div>
</div>
</template>
<script>
export default {
props: ["data"]
};
</script>
<style scoped>
.box {
box-shadow: 10px 10px 5px grey;
}
</style>
I am using mdb theme when the project is uploaded on aws instance footer gets break on right side. I checked the css the width of footer is 100% by default for mdb theme.
Below is the code-
App.vue
<template>
<div id="app">
<div class="flexible-content">
<navbar :page="activePage" />
<main class="mt-5 p-5">
<div class="pt-5">
<router-view></router-view>
</div>
</main>
<div class="white-skin">
<copyrights />
</div>
</div>
</div>
</template>
<script>
import SideNav from './components/SideNav'
import Navbar from './components/Navbar'
import Copyrights from './components/Footer'
import * as vm from "vue";
export default {
name: 'App',
mode:'history',
components: {
SideNav,
Navbar,
Copyrights
},
data () {
return {
activePage: 'dashboard',
toggle: false,
loader:true,
}
},
mounted () {
this.activePage = this.$route.name;
this.$on('toggle', function (value) {
this.toggle = value
});
},
updated () {
this.activePage = this.$route.name
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Footer.vue
<template>
<mdb-footer>
<p class="footer-copyright mb-0 py-3 text-center">
© {{new Date().getFullYear()}} Copyright: xyz
</p>
</mdb-footer>
</template>
<script>
import { mdbFooter } from 'mdbvue'
export default {
name: 'Footer',
components: {
mdbFooter
},
data () {
return {
}
}
}
</script>
<style scoped>
</style>
This is the code of App.vue and Footer.vue .It is perfectly working on localhost but not on instance. After upload on instance footer gets break from right side