I have this code :
<div class="page-payment">
<div class="payment-methods" v-if="!pending">
<sepa-modal
ref="sepaModal"
/>
</div>
</div>
SepaModal.vue :
<b-modal
id="sepaModal"
centered
top
no-fade
size="md"
ref="modal"
hide-footer
#show="showPopup"
#hidden="closePopup"
>
<template #modal-header-close>
<icon width="20" height="20" class="d-none d-md-block" type="times"/>
<icon width="10" height="18" class="d-md-none" type="arrow-left"/>
</template>
<template #modal-title>
</template>
<div>
<div class="content-modal content-modal-sepa">
<div class="modal-header"></div>
..........
</div>
</div>
The .css :
.page-payment {
.payment-methods {
.content-modal {
padding: 20px !important
}
}
}
The style is not getting into account. But I want to keep all styles inside: .page-payment{}. How can I solve it?
Related
I'm new to VueJS, and I'm coming to you to find out if what I've done is feasible or not.
Instead of having old data, while loading components, I prefer to display a preloader.
I liked the idea of a skeletons loader, rather than a simple spinner.
Right now I have a state in the store, which is null by default, I have a mutation to set the loading, and a getter.
To avoid visual bugs, from the router, with a beforeEach, I initialize the loading state to true, so that by default the components start loading !
Then, in my view, I import the Loader component, with its svg and style.
And I place it over the component that needs to be displayed, with a simple condition v-if="!getLoading" and v-if="getLoading".
The problem is that I feel like I'm tinkering with the blind, the beforeach and displaying this component with a condition?
I would be reassured if someone can give me some advice, or approve this method of doing!
Here is the code of a simple Loader component
<template>
<content-loader
:height="78"
:width="390"
:speed="4"
primaryColor="#f2f6fe"
secondaryColor="#e0eafa"
>
<rect x="9" y="20" rx="4" ry="4" width="142" height="13" />
<rect x="316.38" y="5.38" rx="5" ry="5" width="68" height="68" />
<rect x="9" y="46" rx="4" ry="4" width="75.26" height="13.26" />
</content-loader>
</template>
<script>
import { ContentLoader } from "vue-content-loader"
export default {
components: {
ContentLoader
}
}
</script>
The store code
const state = {
loading: null,
}
const mutations = {
SET_LOADING: (state, payload) => {
state.loading = payload;
},
}
const getters = {
getLoading(state) {
return state.loading;
}
}
Example of utilisation in my view : with condition
<div class="col-12 col-lg-4 col-xl-3 col-md-6" v-if="getLoading"> // the condition
<div class="card animate-up-2">
<div class="card-body">
// the component
<StatsLoader></StatsLoader>
</div>
</div>
</div>
<div class="col-12 col-lg-4 col-xl-3 col-md-6" v-if="!getLoading"> // the condition
<div class="card animate-up-2">
<div class="card-body">
<div class="d-flex align-items-center justify-content-between">
<div>
<h3 class="font-weight-bold text-uppercase">5 %</h3>
<div class="d-flex d-sm-block d-lg-flex align-items-end">
<p class="mb-0 mr-2 text-muted">API usage</p>
</div>
</div>
<div>
<div class="avatar avatar-lg">
<div class="avatar-title sred sbg-soft-red rounded">
<i class="fad fa-project-diagram"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
If that is a global loader being used on all the routes, you can wrap it in a component and use that component everywhere. Use named slots to manage your template.
An example of a Loader component:
Loader.vue
<template>
<div>
<slot name='loading' v-if='getLoading'>
<StatsLoader></StatsLoader>
</slot>
<slot name='content v-if='!getLoading'></slot>
</div>
</template>
<script>
import StatsLoader from '#/components/StatsLoader.vue';
export default {
name: 'Loader',
props: {
isLoading: {
type: Boolean,
default: null
}
},
computed: {
getLoading() {
return this.isLoading === null ? this.$store.state.loading : this.isLoading;
}
},
components: {
StatsLoader
}
}
</script>
Also, it would useful to register this component globally so you don't need to include it all the routes. You can do that using Vue.component in your main entry file.
import Loader from '#/components/Loader.vue';
Vue.component('Loader', Loader);
And you can rewrite your current component template like this:
<Loader>
<template v-slot:loader>
<!-- Use a different loader here for this page maybe -->
</template>
<template v-slot:content>
<div class="card animate-up-2">
<div class="card-body">
<div class="d-flex align-items-center justify-content-between">
<div>
<h3 class="font-weight-bold text-uppercase">5 %</h3>
<div class="d-flex d-sm-block d-lg-flex align-items-end">
<p class="mb-0 mr-2 text-muted">API usage</p>
</div>
</div>
<div>
<div class="avatar avatar-lg">
<div class="avatar-title sred sbg-soft-red rounded">
<i class="fad fa-project-diagram"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
</Loader>
Also you can use <Loader :is-loading='isPageLoading' /> in case you don't want to rely on the global loader.
I am trying to have navigation controls displayed horizontally in the upper right hand section of the screen. The following works and displays with each item in a row:
<template>
<div id="navControlPanel">
<div id="controls">
<NavControl />
<NavControl />
<NavControl />
</div>
</div>
</template>
<style>
#navControlPanel{
display: flex;
flex-direction: row;
width: 100px;
height: 50px;
background: purple;
}
#controls{
display: flex;
flex-direction: row;
width: 100%;
}
</style>
yet this does not, and instead displays with them in a column:
<template>
<div id="navControlPanel">
<div id="controls" v-bind:key="control.id" v-for="control in controls">
<NavControl v-bind:control="control" />
</div>
</div>
</template>
NavControl:
<template>
<div id="navControl">
{{control.id}} //Set to just plain text when not dynamically binded
</div>
</template>
<style scoped>
#navControl{
width: 30pt;
height: 30pt;
background: blue;
border-radius: 1000px;
}
</style>
I can't find a logical reason why these would be any different, unless this is some inherent way Vue works that I'm missing.
The issue here seems to be that in the first example you got one div with multiple components in it:
<div id="controls">
<NavControl />
<NavControl />
<NavControl />
</div>
The problem is that in the second example you are creating multiple div elements with the same id and each of them have nested component inside of it.
Here, in a loop, you create multiple div elements with id="controls"
<div id="controls" v-bind:key="control.id" v-for="control in controls">
<NavControl v-bind:control="control" />
</div>
It ends up being something similar to this:
<div id="controls">
<NavControl />
</div>
<div id="controls">
<NavControl />
</div>
<div id="controls">
<NavControl />
</div>
You would probably see it better if you inspected your code in the browser tools.
As a side note: please, keep in mind that if you for whatever reason wanted to do something like this then you would use class instead of id.
Solution:
What you would want to do instead is to create multiple components inside your <div id="controls"></div>.
To do that you would place v-for inside the component and not the outer div.
<NavControl v-for="control in controls" v-bind:control="control" :key="control.id"/>
I am unsure of the actual desired scope, so I will go over both.
If we want multiple controls in the template, as laid out, switch id="controls" to class="controls":
<template>
<div id="navControlPanel">
<div class="controls" v-bind:key="control.id" v-for="control in controls">
<NavControl v-bind:control="control" />
</div>
</div>
</template>
...
.controls {
/* my styles */
}
If the v-for is out of scope, and we only want this ran on those items on NavControl:
<template>
<div id="navControlPanel">
<div class="controls">
<NavControl
v-for="control in controls"
/>
</div>
</div>
</template>
I have problem with triggering next or previous item in vue-owl-carousel package in Vue with javascript.
Can anybody help?
Carousel code :
<carousel id="newGamesCarousel" :items="1" :dots="false" :nav="false" :margin="10" :key="refresh">
<div class="newGames-item" v-for="item in newProducts">
<div class="details">
<div class="labels flex-wrap">
<span class="mb-1" v-for="platform in item.platforms">{{platform.name}}</span>
<span class="mb-1" v-for="region in item.regions">ریجن {{region.name}}</span>
</div>
<h2 class="gameTitle">{{item.name}}</h2>
<div class="priceBox">
<router-link class="add-to-cart" :to="{path: '/game/'+item.id+'/'+stringToSlug(item.title)+''}">+</router-link>
<div class="price">
<div class="former" v-if="item.sale_percent !== false">
<span class="percent">%{{item.sale_percent}}</span>
<span class="total">{{item.price}}</span>
</div>
<div class="later">
{{item.regular_price}}
<span class="unit">تومان</span>
</div>
</div>
</div>
</div>
<figure class="image">
<img v-bind:src="item.thumbnail_url" v-bind:alt="item.name">
</figure>
</div>
</carousel>
And the next and previous buttons:
<div class="arrows">
<svg class="nextCarousel" id="newGamesNext" viewBox="0 0 24 24">
<use xlink:href="/src/assets/imgs/sprite.svg#arrow"></use>
</svg>
<svg class="prevCarousel" id="newGamesPrev" viewBox="0 0 24 24">
<use xlink:href="/src/assets/imgs/sprite.svg#arrow"></use>
</svg>
</div>
as per documentation described here : https://www.npmjs.com/package/vue-owl-carousel
Custom prev and next buttons using slot, the buttons will be hidden
while start and end in non-loop mode
<carousel>
<template slot="prev"><span class="prev">prev</span></template>
<template slot="next"><span class="next">next</span></template>
</carousel>
within the carousel tag after adding all your slides
you can add <template slot="{{prev/next}}">{{add your icon image here }}</template> and it should take care of the previous and next events on its own
<template slot="prev">
<svg class="nextCarousel" id="newGamesNext" viewBox="0 0 24 24"><use xlink:href="/src/assets/imgs/sprite.svg#arrow"></use></svg>
</template>
this is what I feel should solve your issue. If Im missing something feel free to add urls of documentations/ tutorials that you followed to get your code here. please let me know if the solution worked or not
<v-flex>
<span #click="$refs.prev.click()">
PREVIOUS
</span>
<span #click="$refs.next.click()">
NEXT
</span>
</v-flex>
<v-flex>
<carousel>
<template slot="prev"><span hidden ref="prev" class="prev">prev</span></template>
<template slot="next"><span hidden ref="next" class="next">next</span></template>
</carousel>
</v-flex>
I am new with Vue and trying to open sketchpad inside vue-js-modal.
I am not sure what am I doing wrong here.
I am using VueModal and vue-signature-pad.
It works fine on the page but I could not make it run in the modal.
Here is the link to codesandbox
App.vue code is as follow
<template>
<div id="app">
<v-dialog />
<div class="container">
<div class="row">
<div class="col-12 mt-2">
<div class="col-6 mt-2">
<button class="btn btn-secondary" #click="showButtonsDialog">
Open Dialog
</button>
</div>
</div>
<div class="col-12 mt-2">
<VueSignaturePad
id="signature"
width="100%"
height="100%"
ref="signaturePad"
/>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "App",
methods: {
showButtonsDialog() {
this.$modal.show("dialog", {
title: "Some Title",
text:'<VueSignaturePad id="signature" width="100%" height="200px" ref="signaturePad"/>',
buttons: [
{
title: "CANCEL",
handler: () => {
this.$modal.hide("dialog");
}
}]
});
}
}
};
</script>
What am I doing wrong here?
Thank you
I think text only work with plain text, not Vue component. To include Vue component in your modal, you can declare it in template
<modal name="example"
width="80%"
height="80%">
<VueSignaturePad
id="signature"
width="100%"
height="100%"
ref="signaturePad"
/>
</modal>
and when you want to show it
showButtonsDialog() {
this.$modal.show("example")
}
Demo on Codesandbox
I try to open a popover when I click on the "Delete" button.
The problem is that all the popovers of all the "Delete" buttons open at the same time.
Can you help me solve this problem?
I would like the click, only the popover concerned opens. And with the button "cancel", only the button concerned closes.
Thank you !
<template>
<div>
<div v-for="student in students.data">
<div class="col--10">
<avatar v-bind:username="student.name" :size="36" class="col--10"></avatar>
</div>
<div class="t20 col--30">{{ student.name }}</div>
<div class="t20 col--40">{{ student.email }}</div>
<div style="text-align: right" class="col--20">
<el-button icon="el-icon-edit" size="small" #click="editStudent(student)"></el-button>
<el-popover placement="top" width="160"
v-model="deleteStudentPopover">
<p>Are you sure to delete this?</p>
<div>
<el-button size="mini" type="text" #click="deleteStudentPopover = false">cancel</el-button>
<el-button type="primary" size="mini" #click="myDeleteFunction">Yes, delete!</el-button>
</div>
<el-button slot="reference" #click="deleteStudentPopover = true">Delete</el-button>
</el-popover>
</div>
</div>
</div>
</template>
export default {
data() {
return {
deleteStudentPopover: false,
students: []
}
},
}
Use <div v-for="(student, index) in students.data"> then bind/pass index when calling different functions.