Nuxt & Vue Social Chat - javascript

I installed the Vue Social Chat module into my Nuxt app and having trouble to understand how the props and color setting work. At present everything works fine, although the whatsapp Icon displayed is black as well as the top bar situated inside the speech bubble. How would I go about changing this in Nuxt. The author says to use css variables, but I have no idea where to put these and how to use them in my code.
Nuxt also does not have an App.vue so i just imported the module directly which seems to work but I am not sure I am doing it correctly.
This is what my current default.vue page looks like. I do not import the module any place else.
<template>
<v-app dark>
<v-main>
<Nuxt />
</v-main>
<div>
<SocialChat
icon
:attendants="attendants"
>
<p slot="header" >Chat to us on whatsapp for any question, or sales related topics.</p>
<template v-slot:button>
<img
src="https://raw.githubusercontent.com/ktquez/vue-social-chat/master/src/icons/whatsapp.svg"
alt="icon whatsapp"
aria-hidden="true"
>
</template>
<small slot="footer">Opening hours: 8am to 6pm</small>
</SocialChat>
</div>
</v-app>
</template>
<script>
import { SocialChat } from 'vue-social-chat'
export default {
name: 'DefaultLayout',
components: {
SocialChat
},
data() {
return {
attendants: [
{
app: 'whatsapp',
label: '',
name: '',
number: '',
avatar: {
src: '',
alt: ''
}
},
// ...
],
}
},
}
</script>
<style>
.container {
max-width: 1200px;
}
</style>

This is mainly what is needed overall
<template>
<div class="layout">
<nuxt />
<social-chat id="social-button" icon :attendants="attendants">
<p slot="header">
Click on one of our attendants below to chat on WhatsApp.
</p>
<template #button>
<img
src="https://raw.githubusercontent.com/ktquez/vue-social-chat/master/src/icons/whatsapp.svg"
alt="icon whatsapp"
aria-hidden="true"
/>
</template>
<small slot="footer">Opening hours: 8am to 6pm</small>
</social-chat>
</div>
</template>
<script>
import { SocialChat } from 'vue-social-chat'
export default {
name: 'DefaultLayout',
components: {
SocialChat,
},
data() {
return {
attendants: [
{
app: 'whatsapp',
label: 'Technical support',
name: 'Alan Ktquez',
number: '5581983383532',
avatar: {
src: 'https://avatars0.githubusercontent.com/u/8084606?s=460&u=20b6499a416cf7129a18e5c168cf387e159edb1a&v=4',
alt: 'Alan Ktquez avatar',
},
},
],
}
},
}
</script>
<style>
:root #social-button {
--vsc-bg-header: orange;
--vsc-bg-footer: #fafafa;
--vsc-text-color-header: yellow;
--vsc-text-color-footer: green;
--vsc-bg-button: pink;
--vsc-text-color-button: purple;
--vsc-outline-color: #333;
--vsc-border-color-bottom-header: teal;
--vsc-border-color-top-footer: #f3f3f3;
}
</style>
Instead of :root #social-button CSS selector, we may have used --vsc-bg-button: pink !important; too but I don't like to nuke CSS specificity.
Also, the style can be scoped but there is no really implication here anyway because you will not get any scoping issue here.
A github repo can be found here: https://github.com/kissu/vue-social
And a hosted working example available here: https://so-vue-social.netlify.app/

Related

Hiding Popover on internal click

I'm currently using Vue-PopperJS, and have pretty much set it up as they have on the attached link with some slight changes:
<template>
<Popper
ref="popover"
trigger="clickToToggle"
:options="{
placement: position,
}"
>
<slot
slot="reference"
name="activator"
/>
<div class="base-dropdown--dropdown popper">
<slot name="popover" />
</div>
</Popper>
</template>
<script>
import Popper from 'vue-popperjs'
import 'vue-popperjs/dist/vue-popper.css'
export default {
name: 'BaseDropdown',
components: {
Popper
},
props: {
position: {
type: String,
default: 'bottom'
}
}
}
</script>
<style scoped lang="sass">
.base-dropdown
&--dropdown
min-width: 180px
#apply rounded-large shadow-sm
</style>
And for the items inside the popover we created another component like so:
<template>
<div
class="base-dropdown-item"
:class="getDropdownItemClass"
#click="$emit('click')"
>
<slot />
</div>
</template>
<script>
export default {
name: 'BaseDropdownItem',
props: {
hoverable: {
type: Boolean,
required: false
}
},
computed: {
getDropdownItemClass () {
if (this.hoverable) return ['hover:bg-blue']
return []
}
}
}
</script>
<style scoped lang="sass">
.base-dropdown-item
text-overflow: ellipsis
padding: 12px 0 12px 12px
#apply cursor-pointer body-3 flex items-center overflow-hidden text-grey-800 transition-all whitespace-nowrap
&:hover
#apply text-black
</style>
My question is, say I click on the popover content (ie, a button that does something), how can I trigger it to close the popover too?
I know there is an event to hide it but I'm not sure how to use it.
Should you need more information please don't hesitate to ask!
Not sure how 'efficient' this solution is. However, Chase DeAnda's comment gave me an idea for an elegant solution.
I ended up using the EventBus that would $emit('close-popver'). This emit would be from whatever (in this case a <BaseDropDownItem /> component) that calls this method on a #click.
methods: {
handleClick() {
this.$emit('click')
EventBus.$emit('close-popover')
}
}
And to close the popover:
closePopover(){
const { popover } = this.$refs
popover.doClose()
}

Binding a Component property in Vue

Good day everyone! I'm currently learning vue and I'm following a youtube tutorial on building an image carousel from scratch. Here's the code for the Image Carousel parent component:
<template>
<div class = "slides">
<div class = "slides-inner">
<div v-for= "slide in slides">
<Slide v-bind:slide= "slide"></Slide>
</div>
</div>
</div>
<script>
import Slide from './Slide';
export default{
data(){
return{
slides:[
{ src:'src/assets/slide1.jpg' },
{ src:'src/assets/slide2.jpg' },
{ src:'src/assets/slide3.jpg' },
{ src:'src/assets/slide4.jpg' },
{ src:'src/assets/slide5.jpg' }
]
}
},
components: {
Slide
}
}
</script>
<style scoped>
.slides {
align-items: center;
background-color: #666;
color: #999;
display: flex;
font-size: 1.5rem;
justify-content: center;
min-height: 10rem;
}
</style>
and here's the code for the individual image slides:
<template>
<div class="slide">
{{slide.src}}
</div>
</template>
<script>
export default {
data(){
return{}
},
props: {
slide: ['slide']
}
}
</script>
<style scoped>
</style>
The v-bind on the v-for loop on the parent Image Carousel component is supposed to bind the slide.src property to the current slide being looped so that it will display the image in the browser but what I'm getting is a blank browser screen and an error that says the right value of the operator at v-bind is not an object although the tutorial I'm following works exactly as it should with this same code so I'm wondering what I'm doing wrong.
In your slide component, it should be
export default {
data(){
return{}
},
props: {
slide: Object
}
}
You can check valid props type in Vue document
Please also see the Vue Style Guide as prop definitions should be as detailed as possible. An Essential Requirement by the creators of Vue. See Vue Style Guide.

Third party VueJS component can't be found in node_modules

Using vue-cli version 3 for a new vuejs project (I've been studying a lot of vuejs, but this is the first time trying to implement a third-party component). I'm trying to use a grid component that looks impressive. The component is here.
I've setup my environment, installed the grid and component using npm as instructed from their site, configured my own component and imported everything (I thought) properly. I've even setup an data array property to use as a test to fill my grid. I ran npm install and confirmed the folders were installed in my node_modules folder (they are there). Here is my main.js:
import Vue from 'vue'
import App from './App.vue'
import CGrid from 'vue-cheetah-grid'
Vue.config.productionTip = false;
Vue.use(CGrid);
new Vue({
render: h => h(App)
}).$mount('#app')
And here is my App.vue :
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<reports-grid></reports-grid>
</div>
</template>
<script>
import ReportsGrid from './components/ReportsGrid.vue'
export default {
name: 'app',
components: {
reportsGrid: ReportsGrid
}
}
</script>
Here is my component file, ReportsGrid.vue:
<template>
<div class="grid">
<c-grid ref="grid" :data="records" :frozen-col-count="1">
<c-grid-column field="team" width="85">
Team
</c-grid-column>
<c-grid-column-group caption="Estimate">
<c-grid-column field="quotenum">
Quote #
</c-grid-column>
<c-grid-column field="quotedate">
Date
</c-grid-column>
<c-grid-column field="customer">
Customer
</c-grid-column>
<c-grid-column field="country">
Country
</c-grid-column>
<c-grid-column field="type">
Type
</c-grid-column>
<c-grid-column field="quoteamount">
Quote Amount
</c-grid-column>
</c-grid-column-group>
<c-grid-column-group caption="Sales Order">
<c-grid-column field="salesordernum">
Sales Order #
</c-grid-column>
<c-grid-column field="salesorderamount">
Sales Order Amount
</c-grid-column>
<c-grid-column field="margin">
Average Margin
</c-grid-column>
<c-grid-column field="status">
Status
</c-grid-column>
</c-grid-column-group>
</c-grid>
</div>
</template>
<script>
export default {
name: 'app',
data: function() {
return {
records: [
{
team: 'GG', quotenum: '20211', quotedate:'today', customer: 'AirNN', country: 'Peru', salesordernum: '11111',
type: 'Production', quoteamount: '$1300', salesorderamount: '$1200', margin: '25%', status: 'WIN Partial'
},
{
team: 'LL', quotenum: '20200', quotedate:'today', customer: 'Paris', country: 'Mexico', salesordernum: '11122',
type: 'Bid', quoteamount: '$12300', salesorderamount: '$10300', margin: '20%', status: 'WIN Partial'
}
]
}
}
}
</script>
When I run this I don't see anything on my page (no errors either). I noticed in my main.js my linter is throwing an error on the line import CGrid from 'vue-cheetah-grid' (this error doesn't show up in my terminal, just in my main.js:
[ts]
Could not find a declaration file for module 'vue-cheetah-grid'. 'path.to/node_modules/vue-cheetah-grid/dist/vueCheetahGrid.js' implicitly has an 'any' type.
Try `npm install #types/vue-cheetah-grid` if it exists or add a new declaration (.d.ts) file containing `declare module 'vue-cheetah-grid';`
This is a new error to me. The folders are in the node_modules folder. I even tried the npm install #types/vue-cheetah-grid but it still didn't work.
The problem appears to be with the height style.
Looking at the page source for the Cheetah Vue demo, they have dropped in some styles that seem to override the standard cheetah styles.
If you add this to your component, it looks ok
<style scoped>
html {
height: 100%;
}
body {
height: calc(100% - 100px);
}
.contents {
padding: 30px;
box-sizing: border-box;
}
.demo-grid {
width: 100%;
height: 300px;
box-sizing: border-box;
border: solid 1px #ddd;
}
.demo-grid.large {
height: 500px;
}
.demo-grid.middle {
height: 300px;
}
.demo-grid.small {
height: 240px;
}
.log {
width: 100%;
height: 80px;
background-color: #F5F5F5;
}
.hljs {
tab-size: 4;
}
</style>

Why height: 0 can not work in css definition

In my project, I use vue.js 2, and i have an img component.
Here is code of it:
<template>
<div class="banner">
<img class="banner-img" :src="bannerImg"/>
</div>
</template>
<script>
export default {
name: 'DetailBanner',
props: {
sightName: String,
bannerImg: String,
gallaryImgs: Array
}
}
</script>
<style lang="stylus" scoped>
.banner
position: relative
overflow: hidden
height: 0
padding-bottom: 55%
.banner-img
width: 100%
The url of img is :
http://img1.qunarzz.com/sight/p0/201404/23/04b92c99462687fa1ba45c1b5ba4ad77.jpg_600x330_bf9c4904.jpg
Here i don't want to display this img, so i set height:0 in CSS.
But unlucky, It fails. I have tested for removing height: 0, and it shows all the same.
why height: 0 can not work, who can help me?
You could take advantage of Vue.js and use v-if to show/hide your image as follow :
<template>
<div class="banner" v-if="showImg">
<img class="banner-img" :src="bannerImg"/>
</div>
</template>
<script>
export default {
name: 'DetailBanner',
props: {
sightName: String,
bannerImg: String,
gallaryImgs: Array
},
data(){
return{
showImg:false
}
}
}
</script>
you could put showImg in your props, by this way you could change the image state using only Vue.js and avoid struggling with CSS

VueJS error compiling template

I just made my first project with VueJS and Vue-loader.
So I made my first component to show a simple message, it works fine when I make one message, but I get an error when I make multiple messages:
(Emitted value instead of an instance of Error)
Error compiling template:
<message>This is a small message!</message>
<message>Another one</message>
- Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
This is my code. I'm very new to this and I can't figure out what's wrong.
App.vue
<template>
<message>This is a small message!</message>
<message>Another one</message>
</template>
<script>
import Message from './Components/Message.vue';
export default {
name: 'app',
components: {
Message,
},
data () {
return {
}
}
}
</script>
Message.Vue
<template>
<div class="box">
<p>
<slot></slot>
</p>
</div>
</template>
<script>
export default {
}
</script>
<style>
.box { background-color: #e3e3e3; padding: 10px; border: 1px solid #c5c5c5; margin-bottom: 1em;}
</style>
I hope somebody can help!
The error is pretty self-explanatory. You should have only one root element in each component. So just pack everything in a div.
<template>
<div>
<message>This is a small message!</message>
<message>Another one</message>
</div>
</template>

Categories