So I have a SPA with multiple routerlinks linking to multiple vue components. I am trying to link a component with props to only one of those "pages". How should I go about doing that?
Thanks in advance.
This is my main vue page where I connect all my routerlinks together.
<script>
import Footer from "./components/Footer.vue";
import Counter from "./components/Counter.vue";
export default {
components: {
Footer,
Counter,
},
};
</script>
<template>
<header class="Header">Welcome to my app</header>
<nav>
<RouterLink
style="text-decoration: none; color: inherit; padding-right: 20px"
to="/"
>
Home
</RouterLink>
<RouterLink
style="text-decoration: none; color: inherit; padding-left: 20px"
to="/about"
>
About
</RouterLink>
<RouterLink
style="text-decoration: none; color: inherit; padding-left: 20px"
to="/Dice"
>
Dice
</RouterLink>
<RouterLink
style="text-decoration: none; color: inherit; padding-left: 20px"
to="/FAQ"
>
FAQ
</RouterLink>
<RouterLink
style="text-decoration: none; color: inherit; padding-left: 20px"
to="/Calculator"
>
Calculator
</RouterLink>
<RouterLink
style="text-decoration: none; color: inherit; padding-left: 20px"
to="/Clock"
>
Clock
</RouterLink>
<RouterLink
style="text-decoration: none; color: inherit; padding-left: 20px"
to="/Counters"
>
Counters
</RouterLink>
</nav>
<main>
<RouterView></RouterView>
</main>
<Footer :copyrightYear="2022"></Footer>
</template>
<style scoped>
nav {
background-color: rgb(63, 63, 63);
}
.Header {
color: rgb(0, 0, 66);
text-align: center;
font-size: 50px;
}
nav {
text-align: center;
font-size: 30px;
}
</style>
And I would like to add a component to the 'Counters' page, something like this:
<Counter :startValue="0" :incValue="1"></Counter>
<Counter :startValue="45" :incValue="5"></Counter>
<Counter :startValue="33" :incValue="10"></Counter>
the component looks something like this:
<script>
export default {
props: {
startValue: Number,
incValue: Number,
},
methods: {
increment(a, b) {
a = a + b;
console.log(a);
return a;
},
},
};
</script>
<template>
<button #click="increment(startValue, incValue)">
{{ startValue }}
</button>
</template>
<style scoped>
button {
font-size: 20px;
}
</style>
I would like to add this component to my Counters.vue page:
<script>
export default {
components: {},
};
</script>
<template>
<div class="page">
<h1>Let's count!</h1>
<Counter :startValue="0" :incValue="1"></Counter>
<Counter :startValue="45" :incValue="5"></Counter>
<Counter :startValue="33" :incValue="10"></Counter>
</div>
</template>
<style scoped>
.page {
background-color: rgb(251, 255, 0);
text-align: center;
}
button {
font-size: 20px;
padding: 1px;
margin: 10px;
}
</style>
but adding the 'import' or 'components:' lines to the 'Counters.vue' page completely bombs the site. yet it does work fine on the main vue file. How do I link the component to Counters.vue successfully?
You have to import your component directly in the page you are using it and not in the App.vue
CounterView.vue
<script>
import Counter from "./components/Counter.vue";
export default {
components: {
Counter,
},
};
</script>
<template>
<div class="page">
<h1>Let's count!</h1>
<Counter :startValue="0" :incValue="1"></Counter>
<Counter :startValue="45" :incValue="5"></Counter>
<Counter :startValue="33" :incValue="10"></Counter>
</div>
</template>
<style scoped>
.page {
background-color: rgb(251, 255, 0);
text-align: center;
}
button {
font-size: 20px;
padding: 1px;
margin: 10px;
}
</style>
Also I suggest you to have a different name between your component and your page to avoid conflict
e.g:
Counter.vue for the component
CounterView.vue for the page
Related
I'm trying to display an items details on click of a button, I have the data going to the modal properly, but I can't seem to get the modal to actually show up. I've tried different implementations of a modal in the template, and the closes I've gotten was having a grey screen show up on the button press. I'm at a loss of what to do at this point because every tutorial I try on modals doesn't seem to work for me. I'm using VUE CLI version 2
Home.vue
<template>
<div class="home">
<Navbar />
<Ordertiles #childToParent="onClickChild"/>
<div v-if="showModal">
<Modal #close="toggleModal" :header="item.header" :text="item.text" :image="item.img"/>
</div>
</div>
</template>
<script>
// # is an alias to /src
import Navbar from '#/components/Navbar.vue'
import Ordertiles from '#/components/Ordertiles.vue'
import Modal from '#/components/Modal.vue'
export default {
name: 'Home',
components: {
Navbar,
Ordertiles,
Modal
},
data() {
return {
item: '',
showModal: false
}
},
methods: {
toggleModal() {
this.showModal = !this.showModal
},
onClickChild(item) {
this.item = item
console.log(this.item)
this.toggleModal()
}
}
}
</script>
Modal.vue
<template>
<div class="modal">
<div class="container">
<div class="modal__title">Direction</div>
<p>{{header}}</p>
<img v-bind:src="image">
<p> {{text}} </p>
<button class="mt-3 border-b border-teal font-semibold">Close</button>
</div>
</div>
</template>
<script>
export default {
props: ['header', 'text', "image"],
methods: {
close () {
this.$emit('close')
}
}
}
</script>
<style lang="css" scoped>
.modal {
background-color: rgba(0, 0, 0, 0.7);
}
</style>
Before Clicking the button
After button click
Why do not use other npm modal packages like vue-modality .I strong vouch for this package.Its easy to use and understand. This will save you a great amount of time as you dont re-invent the wheel.Check out this link https://www.npmjs.com/package/vue-modality
I found a modal example that actually works for me
Modal.vue
<template>
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot name="body">
default body
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
default footer
<button class="modal-default-button" #click="$emit('close')">
OK
</button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
props: ['header', 'text', "image"],
methods: {
close () {
this.$emit('close')
}
},
components: {
}
}
</script>
<style lang="css" scoped>
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: table;
transition: opacity 0.3s ease;
}
.modal-wrapper {
display: table-cell;
vertical-align: middle;
}
.modal-container {
width: 300px;
margin: 0px auto;
padding: 20px 30px;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
transition: all 0.3s ease;
font-family: Helvetica, Arial, sans-serif;
}
.modal-header h3 {
margin-top: 0;
color: #42b983;
}
.modal-body {
margin: 20px 0;
}
.modal-default-button {
float: right;
}
.modal-enter {
opacity: 0;
}
.modal-leave-active {
opacity: 0;
}
.modal-enter .modal-container,
.modal-leave-active .modal-container {
-webkit-transform: scale(1.1);
transform: scale(1.1);
}
</style>
I have a simple chart created using vue-apex charts that displays the amount of an asset over time, it works great, but the x-axis displays my data with a lot of distance like this:
https://imgur.com/a/IvfkbZS
How can I reduce the distance between the x-axis items like here:
https://imgur.com/a/X10St0D
here is my code:
<template>
<div class="balance-card-container">
<div class="s">
<md-card class="balance-card">
<md-card-header>
<div class="md-title title">{{ title }}</div>
</md-card-header>
<md-card-content>
<p class="number-p">2345</p>
</md-card-content>
</md-card>
<md-card class="second-card">
<!-- <h2 class="users">Assessments summary</h2> -->
<div class="chart-wrapper">
<apexchart width="900" height="200" type="line" :options="options" :series="series"></apexchart>
</div>
</md-card>
</div>
</div>
</template>
<style lang="scss" scoped>
#import "../variables.scss";
.balance-card {
border-radius: 14px !important;
box-shadow: 0px 6px 20px -6px rgba(221, 243, 255, 0.6) !important;
}
.title {
text-align: center;
font-family: Open Sans;
font-style: normal;
font-weight: bold !important;
font-size: 14px;
color: $casal;
}
.number-p {
text-align: center;
font-family: Open Sans;
font-style: normal;
font-weight: bold;
font-size: 28px;
letter-spacing: 0.25px;
color: $casal;
}
.s {
display: flex;
}
.second-card {
width: 900px !important;
}
.chart-wrapper {
width: 100%;
height: 200px;
}
</style>
<script>
export default {
name: "BalanceCard",
props: ["title"],
data() {
return {
options: {
chart: {
id: 'vuechart-example'
},
xaxis: {
categories: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
}
},
series: [{
name: 'series-1',
data: [10000, 5000, 1000]
}]
}
}
}
</script>
I'd like set to different background images for my 'Home' and 'About' components within the react project I'm building. I gave the 'Home' and 'About' components their own stylesheets (styles.css and about.css, respectively), then added a background-image: url() for each, but they both ended up with the 'Home' background.
Any suggestions on how to have different backgrounds for your components, when using react router?
Code as follows:
Home.jsx
import React from 'react'
import './styles.css'
import hashi_logo_2 from './Photos/hashi_logo_2.png'
import {Link} from 'react-router-dom'
function Home() {
return (
<div className = 'home'>
<nav className = 'nav'>
<ul>
<Link to = '/about' style={{ textDecoration: 'none' }} >
<li className='list'>About</li>
</Link>
<li className='list'>Food</li>
<li className='list'>Events</li>
<li className='list'>News</li>
<Link to ='/shop' style={{ textDecoration: 'none' }} >
<li className='list'>Shop</li>
</Link>
<li className='list'>Contact</li>
<li className='list'>Blog</li>
</ul>
</nav>
<main>
<div class='main__image'>
<img src= {hashi_logo_2}/>
</div>
</main>
</div>
)
}
export default Home
styles.css (styling for 'Home')
html * {
box-sizing: border-box;
font-family: 'Permanent Marker', cursive;
}
body {
margin: 0;
padding:0;
background-image: url('./Photos/hashi_pic_blurred_2.jpg');
background-repeat: no-repeat;
background-size: cover;
backdrop-filter: brightness(100%);
}
/* Navigation */
.nav {
background-color:#8b0000;
margin:0;
padding: 15px 0;
opacity: 0.75;
position: fixed;
width:100%;
}
ul {
display:flex;
list-style: none;
flex-direction: row;
justify-content: space-around;
font-size: 20px;
}
.list {
list-style: none;
text-decoration: none;
color: white;
font-size: 25px;
}
.list:hover{
background-color: black;
}
/* Logo */
main {
text-align: center;
padding-top: 130px;
padding-top:180px;
}
img {
max-width: 40%;
height: auto;
}
About.jsx
import React from 'react'
import './about.css'
function About() {
return(
<div className = 'about'>
<p>
Hashigo Zake takes the provision of fine beer to new levels.
<br/>
<br/>
Seven days a week, 362 days a year, we serve the best that New Zealand's booming craft brewing industry has to offer.
We are also building the best range of imported beer that New Zealand has seen.
<br/>
We deal directly with breweries in Australia, Japan and the US and import many of the best beers in the Pacific rim.
<br/>
We also have access to some of the best beers coming from Europe.
<br/>
<br/>
We open at midday every day.
<br/>
Our location is 25 Taranaki St, Te Aro, Wellington, New Zealand.
</p>
<h2>"And he dreamed, and behold a ladder set up on the earth, and the top of it reached to heaven."</h2>
</div>
)
}
export default About
about.css
.about {
height:100%;
background-image: url('./Photos/hashi_taps.jpg');
}
p {
margin-top: 50px;
color: white;
text-align: center;
font-size: 30px;
/* background-color: rgb(139,0,0, 0.75); */
font-family: 'Open Sans', sans-serif;
padding-left: 50px;
padding-right: 20px;
transform: translateY(20%);
font-weight: bold;
}
h2 {
color: white;
text-align: center;
font-size: 40px;
padding-left: 20px;
padding-right: 20px;
margin-top: 400px;
transform: translateY(-450%);
}
import React from 'react';
import Home from './Home'
import About from './About'
import Shop from './Shop'
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom'
function App() {
return (
<Router>
<div>
<Switch>
<Route path ='/' exact component = {Home}/>
<Route path = '/about' component = {About}/>
<Route path = '/shop' component = {Shop}/>
</Switch>
</div>
</Router>
)
}
export default App;
I am using react for making an app project using contextHook and reducerHook but getting:
TypeError: Cannot read property 'map' of undefined
The same code was working a few days back, but now it's giving that error. I've wasted so many hours trying to finding answers on the internet, but I couldn't get any help... Here are pictures of the error and my code as well:
Complete code on Github repo
Error Pic 1
Error Pic 2
Error Pic 3
//App.js
import React from 'react';
import './App.css';
import Header from './Header';
import Balance from './Balance';
import AccSummary from './AccSummary';
import TransactionHistory from './Transactionhistory';
import AddTransaction from './AddTransaction';
function App() {
return (
<div className='container'>
<Header />
<Balance />
<AccSummary />
<TransactionHistory />
<AddTransaction />
</div>
);
}
export default App;
//Transaction.js
import React from 'react';
export const Transaction = ({transObj}) => {
return (
<li>
<span>{transObj.description}</span>
<span> {transObj.amount} </span>
</li>
)
}
//TransactionHistory.js
import React, { useContext } from 'react';
import { TransactionContext } from './TransContext';
import { Transaction } from './Transaction';
function TransactionHistory() {
let {transactions} = useContext(TransactionContext);
return (
<div>
<h2> History </h2>
<hr />
<ul className='transaction-list'>
{transactions.map(transObj => (
<Transaction key={transactions.id} transactions = {transactions} />
))}
//Add Transaction.js
import React from 'react';
function AddTransaction() {
return (
<div>
<h2 className='AddTrans'> <br /> Add New Transaction</h2>
<hr />
<form className = 'transaction-form'>
<label>
Enter Description <br />
<input type='text'
placeholder='Enter Detail of Transaction' className='color'/> <br />
</label>
<label>
Enter Amount <br />
<input type='Number'
placeholder='Enter Transaction Amount'/>
</label>
<br />
<input className='button' type="submit" value="Add Transaction"/>
</form>
</div>
);
}
export default AddTransaction;
//TransContezt.js
import { createContext } from "react";
const initialTransaction = [
{amount: 500, description: 'Cash'},
{amount: -200, description: 'Bill'}
]
export const TransactionContext = createContext(initialTransaction);
//App.css
.container {
width: 350px;
min-height: 700px;
margin: 0 auto ;
background-color:white;
box-shadow: 0 0 10px gray;
margin-top: 50px;
padding: 10px 50px;
font-family: "Times New Roman", Times, serif;
background-image: url("1.png"), url("2.png"), url("3.png"), url("4.png");
background-position: left top, left top, left top, left top ;
background-repeat: repeat-x;
background-size: 100% 20%, 100% 55%, 100% 75%, 100% 100%;
}
.text-centre{
text-align: center;
justify-content: space-between;
background-color: #98DBC6;
border-radius: 5px;
display: grid;
justify-content: space-around;
}
.accsumm{
display: flex;
justify-content: space-around ;
background-color: #5BC8AC;
box-shadow: 0 0 10px gray;
border: thin;
font-family: Arial, Helvetica, sans-serif;
border-radius: 5px;
}
.AddTrans{
margin: 10px 0 0;
}
.transaction-form input{
width: 97%;
margin: 10px 0;
padding: 15px 5px;
border-radius: 5px;
color: white;
}
.color{
color: white;
}
.transaction-list{
margin: 0;
padding: 0;
}
.transaction-list > li{
display: flex;
justify-content: space-between;
box-shadow: 0 0 10px gray;
padding: 10px 5px;
background-color: honeydew;
margin: 5px 0;
border-radius: 5px;
}
.button {
width: 100%;
display: flex;
justify-content: space-around;
box-shadow: 0 0 10px gray;
padding: 10px 10px;
background-color: rgb(138, 179, 255);
margin: 10px 0;
border-radius: 5px;
font-size: larger;
font-weight: bolder;
align-self: center;
}
Tr
For the TransactionHistory component:
The default context value is an array but you destructure it like an object.
In the mapping function, you are passing the original array as a prop instead of the element.
Here is an updated version:
function TransactionHistory() {
const transactions = useContext(TransactionContext);
return (
<div>
<h2> History </h2>
<hr />
<ul className="transaction-list">
{transactions.map((transObj, index) => (
<Transaction key={index} transaction={transObj} />
))}
</ul>
</div>
);
}
Then, in the Transaction component, it is expecting transObj prop but its parent passes in transaction prop. So you might fix it as well:
import React from "react";
const Transaction = ({ transObj }) => {
return (
<li>
<span>{transObj.description}</span>
<span> {transObj.amount} </span>
</li>
);
};
I am building a simple vue app and I encountered a strange issue where the components in my tag are rendered a second time inside the tag.
Originally, the and components were not in a header tag but they appeared below the component.
App.vue
<template>
<div id="app">
<header><app-logo/><nav-bar/></header>
<section class="container">
<router-view/>
</section>
</div>
</template>
<script>
import AppLogo from './components/AppLogo.vue'
import Home from './components/Home.vue'
export default {
name: 'App',
components: {
Home,
AppLogo
}
}
</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;
}
.container {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
.title {
font-family: "Quicksand", "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; /* 1 */
display: block;
font-weight: 300;
font-size: 100px;
color: #35495e;
letter-spacing: 1px;
}
.subtitle {
font-weight: 300;
font-size: 42px;
color: #526488;
word-spacing: 5px;
padding-bottom: 15px;
}
.links {
padding-top: 15px;
}
</style>
nav-bar component:
<template>
<div>
<h1> TFJS/Vue Examples </h1>
<div v-for="page in pages" v-bind:key="page">
<div>
<div>
<router-link to='/basic-logistic-regression'> {{ page }} </router-link>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
pages: ['/BasicLogisticRegression']
}
}
}
</script>
I want to have nav-bar component appear above the router view at all times.
I solved this problem by using a mounted method called loadHome() which uses this.$router.push('/home') to programatically force the router-view to load the homepage component.
here is the code
App.vue
<template>
<div id="app">
<div class="routing">
<header><app-logo/><nav-bar/></header>
</div>
<section class="container">
<router-view/>
</section>
</div>
</template>
<script>
import AppLogo from './components/AppLogo.vue'
import NavBar from './components/NavBar.vue'
import Home from './components/Home.vue'
export default {
name: 'App',
components: {
Home,
AppLogo,
NavBar
},
methods: {
loadHome: function(){
this.$router.push('/home')
}
},
mounted: function(){
this.loadHome()
}
}
</script>