How to use a component in only one router link - javascript

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

Vue.js Modal component shows up in component list, but the modal doesn't actually show

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>

How to shorten space between x-axis labels in vue-apex chart

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>

How do I set unique background images for react router components?

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;

TypeError: Cannot read property 'map' of undefined - React app - useContext and useReducer issue

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>
);
};

Vue <router-view/> loads header components twice

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>

Categories

Resources