Add Font Style and font size in Vue2-editor - vue.js

I wanted to add font style here like there is an option if you want the font to be arial,san-serif etc... But now the font and font sizes not display in vue2-editor. Can anyone help me?
You can access the code here :
https://codesandbox.io/s/liz23?file=/src/App.vue:0-553
this is the code:
<template>
<div id="app">
<vue-editor v-model="content"></vue-editor>
<div v-html="content"></div>
</div>
</template>
<script>
import { VueEditor } from "vue2-editor";
export default {
components: {
VueEditor
},
data() {
return {
content: "<p>Some initial content</p>"
};
}
};
</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>

My answer is based of the excellent answers over at How to add font types on Quill js with toolbar options?. The only thing that I need to change is to use const fonts = Quill.import('formats/font');. vue2-editor exports the Quill object, so you can simply import it as such:
import { VueEditor, Quill } from "vue2-editor";
Then, it is mostly copy-and-pasting the solution in this posted answer. The vue2-editor unfortunately does not expose the default toolbar settings, so you will need to copy it verbatim from the source code and then add your font dropdown manually:
customToolbar: [
// Copied from source
// https://github.com/davidroyer/vue2-editor/blob/master/src/helpers/default-toolbar.js
[{ header: [false, 1, 2, 3, 4, 5, 6] }],
["bold", "italic", "underline", "strike"], // toggled buttons
[
{ align: "" },
{ align: "center" },
{ align: "right" },
{ align: "justify" }
],
["blockquote", "code-block"],
[{ list: "ordered" }, { list: "bullet" }, { list: "check" }],
[{ indent: "-1" }, { indent: "+1" }],
[{ color: [] }, { background: [] }],
["link", "image", "video"],
["clean"],
// This is what I have added
[{ 'font': fonts.whitelist }],
]
See proof-of-concept here: https://codesandbox.io/s/vue2-editor-demo-forked-35wo1?file=/src/App.vue

Related

Tabulator header color

Tabulator does not accept header color change
Through the css below, I'm trying to change the header color of all my columns, but I'm not getting this adjustment
tried to do it this way but it's not going.
I use vue3 + vite + tabulator 5.4
<style scoped>
.tabulator {
font-size: 12px;
width: 100%;
}
.tabulator .tabulator-header,
.tabulator-col .headerBackgroundColor {
background-color: #acacac;
}
</style>
this is my tabulator
tabulator.value = new Tabulator('#tabulator', {
data: dataRelatorio.value,
layout: 'fitColumns',
autoResize: true,
pagination: 'local',
paginationSize: 20,
rowHeight: 25,
paginationSizeSelector: [10, 20, 30, 50, 100, 200, 500, 1000],
movableColumns: true,
paginationCounter: 'rows',
responsiveLayout: 'hide',
placeholder: 'No record found',
locale: 'pt-BR',
langs: {
'pt-BR': {
pagination: {
page_title: 'Show page',
first: 'First',
first_title: 'First page',
last: 'Next',
last_title: 'Next page',
prev: 'Previous',
prev_title: 'Previous page',
next: 'Next',
next_title: 'Next Page',
all: 'All',
},
},
},
columns: columns,
rowFormatter: function (row) {
//console.log(row.getData());
if (row.getData().in_delayed === 'delayed') {
const children = row.getElement().childNodes;
children.forEach((child) => {
child.style.backgroundColor = '#FFFACD';
});
}
},
});
This should work:
<style>
.tabulator .tabulator-header .tabulator-col {
background-color: #acacac;
}
</style>
Notes:
I didn't use the scoped directive on <style> tag.
you can have more than one <style> tag in a component, some scoped and some regular. The regular ones are "normal" CSS, they apply to the entire DOM.
you can also apply the above styles inside a scoped style tag. The selector would most likely be .tabulator :deep(.tabulator-header .tabulator-col), but I can't know for sure until you provide a runnable minimal example, so I could inspect it.

exporting bootstrap table to excel or pdf

I'm using bootstrap vue table and I've want to export a bootstrap table to excel or pdf. It's like a table inside a table and I'm finding it difficult as to how to export it for downloading as excel or pdf as the other solutions I have come around are all involve just giving the json data and it does the work but can't find any solution regarding my problem.
Codesandbox demonstration
<template>
<div id="app">
<b-button #click="exportTable" class="mb-3">Export</b-button>
<b-table-simple outlined id="htmltable">
<b-thead class="b-table__head">
<b-tr>
<b-th class="small-tab">Goods</b-th>
<b-th>Units</b-th>
<b-th>Price Per Unit</b-th>
<b-th>Total Price</b-th>
</b-tr>
</b-thead>
<b-tbody v-for="(service, index) in goodsGroupedByCategory" :key="index">
<b-tr class="category-line">
<b-th class="small-tab cs-textstyle-paragraph-small-bold">{{
index
}}</b-th>
<b-td></b-td>
<b-td></b-td>
<b-th class="cs-textstyle-paragraph-small-bold">{{
service.reduce(function (prev, curr) {
return prev + curr.total_units * curr.price_per_unit;
}, 0)
}}</b-th>
</b-tr>
<b-tr
v-for="serviceItem in service"
:key="serviceItem.id"
class="item-line"
>
<b-td class="big-tab cs-textstyle-paragraph-small">{{
serviceItem.billing_sku_name
}}</b-td>
<b-td class="cs-textstyle-paragraph-small">{{
serviceItem.total_units
}}</b-td>
<b-td class="cs-textstyle-paragraph-small">{{
serviceItem.price_per_unit
}}</b-td>
<b-td class="cs-textstyle-paragraph-small">{{
serviceItem.total_units * serviceItem.price_per_unit
}}</b-td>
</b-tr>
</b-tbody>
</b-table-simple>
</div>
</template>
<script>
import _ from "lodash";
export default {
name: "App",
components: {},
data() {
return {
invoice: [
{
id: "123",
billing_sku_id: "FOOD_ITEMS",
billing_sku_name: "Rice",
total_units: 1,
billing_sku_category: "Food Items",
price_per_unit: 3,
},
{
id: "456",
billing_sku_id: "FOOD_ITEMS",
billing_sku_name: "Wheat",
total_units: 3,
billing_sku_category: "Food Items",
price_per_unit: 5,
},
{
id: "789",
billing_sku_id: "ELECTRICITY_ITEMS",
billing_sku_name: "Bulb",
total_units: 5,
billing_sku_category: "Electricity Items",
price_per_unit: 50,
},
],
};
},
computed: {
goodsGroupedByCategory() {
return _.groupBy(this.invoice, "billing_sku_category");
},
},
methods: {
exportTable() {
console.log("hello");
},
},
};
</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;
padding: 10px;
}
</style>
I found a solution with the help of vue-html2pdf package. First I created a separate component called TableCompo and the code of it comes here:
TableCompo.vue:
<template>
<div id="tableMe">
<b-table-simple outlined id="htmltable">
<b-thead class="b-table__head">
<b-tr>
<b-th class="small-tab">Goods</b-th>
<b-th>Units</b-th>
<b-th>Price Per Unit</b-th>
<b-th>Total Price</b-th>
</b-tr>
</b-thead>
<b-tbody v-for="(service, index) in goodsGroupedByCategory" :key="index">
<b-tr class="category-line">
<b-th class="small-tab cs-textstyle-paragraph-small-bold">{{
index
}}</b-th>
<b-td></b-td>
<b-td></b-td>
<b-th class="cs-textstyle-paragraph-small-bold">{{
service.reduce(function (prev, curr) {
return prev + curr.total_units * curr.price_per_unit;
}, 0)
}}</b-th>
</b-tr>
<b-tr
v-for="serviceItem in service"
:key="serviceItem.id"
class="item-line"
>
<b-td class="big-tab cs-textstyle-paragraph-small">{{
serviceItem.billing_sku_name
}}</b-td>
<b-td class="cs-textstyle-paragraph-small">{{
serviceItem.total_units
}}</b-td>
<b-td class="cs-textstyle-paragraph-small">{{
serviceItem.price_per_unit
}}</b-td>
<b-td class="cs-textstyle-paragraph-small">{{
serviceItem.total_units * serviceItem.price_per_unit
}}</b-td>
</b-tr>
</b-tbody>
</b-table-simple>
</div>
</template>
<script>
import _ from "lodash";
export default {
name: "TableCompo",
data() {
return {
invoice: [
{
id: "123",
billing_sku_id: "FOOD_ITEMS",
billing_sku_name: "Rice",
total_units: 1,
billing_sku_category: "Food Items",
price_per_unit: 3,
},
{
id: "456",
billing_sku_id: "FOOD_ITEMS",
billing_sku_name: "Wheat",
total_units: 3,
billing_sku_category: "Food Items",
price_per_unit: 5,
},
{
id: "789",
billing_sku_id: "ELECTRICITY_ITEMS",
billing_sku_name: "Bulb",
total_units: 5,
billing_sku_category: "Electricity Items",
price_per_unit: 50,
},
],
};
},
computed: {
goodsGroupedByCategory() {
return _.groupBy(this.invoice, "billing_sku_category");
},
},
}
</script>
<style scoped>
#tableMe {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
padding: 10px;
}
</style>
After that I created a parent component (or a view) that using this component and vue-html2pdf package to export the content of table as pdf:
TableView.vue:
<template>
<div>
<b-button #click="generateReport" class="mb-3">Export</b-button>
<!-- first usage of table component: this is for showing the table in browser for users -->
<table-compo></table-compo>
<vue-html2pdf
:show-layout="false"
:float-layout="true"
:enable-download="true"
:preview-modal="false"
:paginate-elements-by-height="1400"
filename="my-table"
:pdf-quality="2"
:manual-pagination="false"
pdf-format="a5"
pdf-orientation="landscape"
pdf-content-width="100%"
ref="html2Pdf"
>
<section slot="pdf-content">
<!-- second usage of table component: this is for putting the contents of table to final pdf -->
<table-compo></table-compo>
</section>
</vue-html2pdf>
</div>
</template>
<script>
import VueHtml2pdf from 'vue-html2pdf';
import TableCompo from '../components/TableCompo'
export default {
name: "TableView",
components: {
VueHtml2pdf,
TableCompo
},
methods: {
/*
Generate Report using refs and calling the
refs function generatePdf()
*/
generateReport () {
this.$refs.html2Pdf.generatePdf();
}
},
}
</script>
<style scoped>
</style>
If you are not happy with my settings, see the documentation of that package to find your desired settings.
You have this package: https://www.npmjs.com/package/xlsx
In your html, create a button and with the #click="exportInvoiceButton()". That's one of the way you can do it in Frontend, but, alternatively, and probably the best way to do this export is from the backend, so you can have more flexibility of what to export.
import XLSX from 'xlsx';
//...
methods: {
//...
exportInvoiceButton() {
const invoices = this.invoices.reduce((ac, invoice) => {
ac.push({
billing_sku_id: invoice.billing_sku_id,
billing_sku_name: invoice.billing_sku_name,
total_units: invoice.total_units,
// ...
});
return ac;
}, [])
var invoicesWS = XLSX.utils.json_to_sheet(invoices)
// A workbook is the name given to an Excel file
var wb = XLSX.utils.book_new() // make Workbook of Excel
// add Worksheet to Workbook
// Workbook contains one or more worksheets
XLSX.utils.book_append_sheet(wb, invoicesWS, 'Invoices list') // invoices list is name of Worksheet
// export Excel file
XLSX.writeFile(wb, 'Invoices.xlsx')
}
//...
}

Vue 3 cli-service app: "Slot "default" invoked outside of the render function" warning when component with slots is imported from other component

MCVE
I have a Tabpane component that takes slots as input. When imported from the template it works as expected.
<Tabpane>
<div caption="I am div 1">Div 1</div>
<div caption="I am div 2">Div 2</div>
</Tabpane>
However when imported from an other component ( Composite in the example ), then it triggers the following warning:
Slot "default" invoked outside of the render function:
this will not track dependencies used in the slot. Invoke the slot function inside the render function instead.
// src/components/Composite.js
import { defineComponent, h } from "vue";
import Tabpane from "./Tabpane.vue";
export default defineComponent({
name: "Composite",
setup() {
const slots = [
h("div", { caption: "I am div 1" }, ["Div 1"]),
h("div", { caption: "I am div 2" }, ["Div 2"])
];
return () => h(Tabpane, {}, () => slots);
}
});
Solved.
The problem was that I called slots.default() from within setup, but not within the returned render function.
Also this component reflected a very beginner approach to reactivity. By now I know better. The old problematic solution is still there in src/components/Tabpane.vue.
The right solution that triggers no warning is:
// src/components/Tabpane2.vue
<script>
import { defineComponent, h, reactive } from "vue";
export default defineComponent({
name: "Tabpane2",
props: {
width: {
type: Number,
default: 400,
},
height: {
type: Number,
default: 200,
},
},
setup(props, { slots }) {
const react = reactive({
selectedTab: 0,
});
return () =>
h("div", { class: ["vertcont"] }, [
h(
"div",
{
class: ["tabs"],
},
slots.default().map((tab, i) =>
h(
"div",
{
class: {
tab: true,
selected: i === react.selectedTab,
},
onClick: () => {
react.selectedTab = i;
},
},
[tab.props.caption]
)
)
),
h(
"div",
{
class: ["slotscont"],
style: {
width: `${props.width}px`,
height: `${props.height}px`,
},
},
slots.default().map((slot, i) =>
h(
"div",
{
class: {
slot: true,
active: react.selectedTab === i,
},
},
[slot]
)
)
),
]);
},
});
</script>
<style>
.tab.selected {
background-color: #efe;
border: solid 2px #afa !important;
border-bottom: transparent !important;
}
.tab {
background-color: #eee;
}
.tabs .tab {
padding: 5px;
margin: 2px;
border: solid 2px #aaa;
border-radius: 8px;
border-bottom: transparent;
cursor: pointer;
user-select: none;
transition: all 0.5s;
color: #007;
}
.tabs {
display: flex;
align-items: center;
margin-left: 5px;
}
.vertcont {
display: flex;
flex-direction: column;
margin: 3px;
}
.slotscont {
position: relative;
overflow: scroll;
padding: 5px;
border: solid 1px #777;
}
.slot {
visibility: hidden;
position: absolute;
}
.slot.active {
visibility: visible;
}
</style>
Slots need to be invoked within the render function and or the <template> box to ensure they keep their reactivity.
A full explanation can be found in this post: https://zelig880.com/how-to-fix-slot-invoked-outside-of-the-render-function-in-vue-3

How to use custom fonts in TinyMCE using tinymce-vue package for VueJS?

I'm trying to use custom fonts stored in my assets/fonts folder with TinyMCE, but it seems like it can't render the font, except for the format selector. The content doesn't display the font correctly, although the font selector shows the font is being applied (in the title, for example).
Here's the code so far:
<template>
<tinymce-editor
:key="id"
:initial-value="initialValue"
:resize="false"
:init="{
selector: 'textarea#format-custom',
height: height,
plugins: 'table wordcount link lists',
menubar : false,
statusbar : false,
toolbar: 'undo redo | bold italic| styleselect | alignleft aligncenter alignright alignjustify | numlist bullist | fontselect',
content_css: [ '//www.tiny.cloud/css/codepen.min.css' ],
content_style: 'body { font-family: Roboto Light; font-size: 16px; }' + '.left { text-align: left; }' + 'img.left { float: left; }' + 'table.left { float: left; }' + '.right { text-align: right; }' + 'img.right { float: right; }' + 'table.right { float: right; }' + '.center { text-align: center; }' + 'img.center { display: block; margin: 0 auto; }' + 'table.center { display: block; margin: 0 auto; }' + '.full { text-align: justify; }' + 'img.full { display: block; margin: 0 auto; }' + 'table.full { display: block; margin: 0 auto; }' + '.bold { font-weight: bold; }' + '.italic { font-style: italic; }' + '.underline { text-decoration: underline; }' + '.title { font-family: Raleway Bold; font-size: 26px; }' + '.subtitle { font-family: Roboto Medium; font-size: 20px; }',
formats: {
alignleft: { selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'left' },
aligncenter: { selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'center' },
alignright: { selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'right' },
alignfull: { selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'full' },
bold: { inline: 'span', classes: 'bold' }, italic: { inline: 'span', classes: 'italic' },
titleformat: { inline: 'span', attributes: { title: 'Title'} , classes: 'title', },
subtitleformat: { inline: 'span', attributes: { title: 'SubTitle'} , classes: 'subtitle' } },
style_formats: [ { title: 'Title', format: 'titleformat' }, { title: 'SubTitle', format: 'subtitleformat' } ]
}"
api-key="no-api-key"
model-events="change keydown blur focus paste"
#input="handleInput"
#error="handleError"
/>
</template>
<script>
import Editor from '#tinymce/tinymce-vue'
export default {
components: {
'tinymce-editor': Editor
},
props: {
initialValue: {
type: String,
default: null
},
id: {
type: String,
default: null
},
height: {
type: String,
default: '100%'
}
},
methods: {
handleInput (value) {
this.$emit('input', value)
},
handleError (err) {
console.error(err)
}
}
}
</script>
Here's a print:
If you want to use custom fonts you need to:
Load them into TinyMCE via content_css
Include the fonts via the font_formats configuration option: https://www.tiny.cloud/docs/configure/editor-appearance/#font_formats
You appear to be loading the CSS from the TinyMCE demo site:
content_css: [ '//www.tiny.cloud/css/codepen.min.css' ],
This is likely not something you want to do as our demo CSS would likely not be appropriate for your web site/application. I would change that to use an appropriate CSS for your site. In that CSS you can load a custom font. For example:
#import url('https://fonts.googleapis.com/css?family=Lato');
Note: The reason the TinyMCE menu can render the font is you are likely loading the font on the page that includes TinyMCE but not in TinyMCE itself. The editor content is in its own iframe but the menus are part of the main page. If you inspect the DOM you will be able to see this layout. Using content_css allows you to inject CSS into the editor's iframe.

Nuxt / Vuex / Vue Reactivity Issue Increment

Hi everyone I am I having some difficulty when working with Nuxt and Vuex.
I am trying to run through the example Vuex / Nuxt Classic Mode.
https://nuxtjs.org/guide/vuex-store/
After clicking my increment button I dont see the number go up. My page just stays at 0, I can see within the console that the state knows the number is no longer 0 but not on the screen, as if it doesnt know to be reactive.
My assumption is that I have miss configured something somewhere and my 0 is not the actual state, but I created some copy of it somehow.
Here is my button within my template.
<button #click="inc">{{ counter }}</button>
Here is my inc function within my methods.
inc () {
this.$store.commit('increment')
},
Here is my computed
computed: {
counter () {
return this.$store.getters.counter
}
}
Here is my Vuex/index.js file contained within the store folder.
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const createStore = () => {
return new Vuex.Store({
state: () => ({
counter: 0
}),
getters: {
counter: state => state.counter
},
mutations: {
increment (state) {
state.counter++
}
}
})
}
export default createStore
Update: Included more code snippets, and replied to existing comments.
#Boussadjra Brahim #xaviert, thank you both for weighing in, I appreciate the assistance.
#Boussadjra Brahim - Yes, I had tried using an action that called the mutation, that didnt seem to get me there either. I also tried adjusting the state via the action alone, and wasnt able to make any changes, however that seems correct, as I am under the impression that actions call mutations to make state changes and do not themselves do so, please correct me if you know more. I am 100% open to the idea that I did not attempt it correctly. Below is that action that didnt do anything and the one that called the mutation
actions: {
increment (state) {
state.counter++
}
},
And here is the version with the action calling the mutation.
actions: {
incrementCounterUp () {
this.commit('increment')
}
},
#xaviert - I have tried starting the server over, and have also tried to see if an nuxt build followed by a firebase serve, to see if maybe that helped. It did not. My normal server start is 'npm run dev'. In hopes that you/anyone else may be able to find my mistake below is my full _id.vue component and also my nuxt.config.js file as maybe that's it. Its still pretty raw and could use a lot of refactoring so hope you can sort through it well enough.
_.id.vue
<template>
<div class="product">
<div class="product-image">
<div class="product-image-img">
<img v-bind:src="product.image_file" width="450px;"/>
</div>
</div>
<div class="product-details-wrapper">
<div class="product-details">
<h1>
<div v-if="this.$route.query.editPage">
<textarea #input="updateTextArea" ref="textarea2" v-model="product.item_name" type="text" />
</div>
<div v-else>{{product.item_name}}</div>
</h1>
<div class="product-description">
<div class="product-description-text" v-if="this.$route.query.editPage">
<textarea #input="updateTextArea" ref="textarea" v-model="product.description" type="text" />
</div>
<div class="product-description-text" v-else v-html="product.description"></div>
</div>
<p class="product-brand"><strong>Brand - </strong> {{product.brand_name}}</p>
<hr />
<div class="product-price">
<div v-if="this.$route.query.editPage">
<strong>Original Price - </strong>
<input v-model="product.msrp" type="text" />
</div>
<div v-else class="product-msrp">
<strong>Original Price - </strong>
<span class="strike">${{product.msrp}}</span>
</div>
<div v-if="this.$route.query.editPage">
<strong>Sale Price - </strong>
<input v-model="product.price" type="text" />
</div>
<div v-else class="product-sale-price">
<strong>Sale Price - </strong>
<span class="">${{product.price}}</span>
</div>
<div class="product-price">
Quantity x
<input #input="updateQuantity" v-model="quantity" min="1" class="" type="number" value="1" />
</div>
<button #click="inc">{{ counter }}</button>
</div>
</div>
</div>
<div v-if="this.$route.query.editPage" class="update-product"> <button #click="updateProduct(product)">Update</button></div>
<div class="footer">
<router-link to="/privacy-policy" target="_blank">Privacy</router-link> |
<router-link to="/terms" target="_blank">Terms</router-link>
</div>
</div>
</template>
<script>
// # is an alias to /src
import firebase from '#/services/fireinit'
import foo from '#/components/foo'
const db = firebase.firestore()
export default {
name: 'ProductPage',
head () {
return {
title: this.product.item_name
}
},
components: {
foo
},
data: function () {
return {
product: {},
image: '',
name: 'Checkout',
description: '',
currency: 'USD',
amount: '',
msrp: '',
quantity: 1
}
},
methods: {
inc () {
this.$store.dispatch('incrementCounterUp', true)
},
updateProduct: function (product) {
db.collection('products').doc(product.item_id).set(product)
.then(function () {
console.log('Document successfully written!')
})
.catch(function (error) {
console.error('Error writing document: ', error)
})
},
updateQuantity () {
this.product.msrp = (this.quantity * this.product.orgMsrp)
this.product.msrp = Math.round(100 * this.product.msrp) / 100
this.product.price = this.quantity * this.product.orgPrice
this.product.price = Math.round(100 * this.product.price) / 100
},
updateTextArea () {
this.$refs.textarea.style.minHeight = this.$refs.textarea.scrollHeight + 'px'
this.$refs.textarea2.style.minHeight = this.$refs.textarea2.scrollHeight + 'px'
}
},
async asyncData({app, params, error}) {
const ref = db.collection("products").doc(params.id)
let snap
let thisProduct = {}
try {
snap = await ref.get()
thisProduct = snap.data()
thisProduct.orgMsrp = thisProduct.msrp
thisProduct.orgPrice = thisProduct.price
} catch (e) {
// TODO: error handling
console.error(e)
}
return {
product: thisProduct
}
},
mounted () {
if(this.$refs.textarea) {
this.$refs.textarea.style.minHeight = this.$refs.textarea.scrollHeight + 'px'
this.$refs.textarea2.style.minHeight = this.$refs.textarea2.scrollHeight + 'px'
}
},
computed: {
counter () {
return this.$store.getters.counter
}
}
}
</script>
<style lang="less">
body {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
margin: 0
}
p{
margin-top: 1em;
margin-bottom: 1em;
}
html, body, #__nuxt, #__layout, .default, .product{
height: 100%;
}
.product {
justify-content: center;
display: flex;
max-width: 1150px;
margin: 0 auto;
flex-wrap: wrap;
align-items: center;
padding: 0 24px;
&-price{
input {
border: 1px solid;
padding: 0 .3em;
text-align: center;
width: 50px;
}
}
}
.product-details{
width: 100%;
textarea {
width: 100%;
font-size: inherit;
color: inherit;
font-family: inherit;
font-weight: inherit;
height: initial;
resize: none;
background-color: transparent;
border: none;
}
h1{
font-size: 1.9rem;
margin: 15px 0 20px;
}
hr{
width: 50%;
margin: .5rem 0px;
}
p{
}
}
.product-description-text{
margin: 10px 0;
}
.product-image, .product-details-wrapper{
align-items: center;
display: flex;
justify-content: center;
}
.product-details-wrapper{
flex: 0 1 535px;
}
.product-image{
flex: 0 1 535px;
img{
width: 100%;
}
}
.product-price{
.strike{
text-decoration: line-through;
}
button{
display: flex;
width: 150px;
height: 50px;
border-radius: 5px;
justify-content: center;
font-size: 24px;
margin-top: 20px;
&:hover{
cursor: pointer;
background-color: #f1f1f1;
box-shadow: 3px 3px 11px -1px rgba(0, 0, 0, 0.48);
}
}
}
.product-sale-price{
color: #f30000;
}
.footer {
flex: 1 1 100%;
text-align: center;
color: #ccc;
margin-top: 25px;
padding: 15px;
a {
color: #ccc;
text-decoration: none;
&:hover{
text-decoration: underline;
}
}
}
.update-product{
position: absolute;
top: 0;
text-align: center;
}
</style>
nuxt.confgs.js
const pkg = require('./package')
const { STRIPE_TOKEN } = process.env;
module.exports = {
vue: {
config: {
productionTip: false,
devtools: true
}
},
buildDir: './functions/nuxt',
mode: 'universal',
/*
** Headers of the page
*/
head: {
title: pkg.name,
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: pkg.description }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
/*
** Customize the progress-bar color
*/
loading: { color: '#fff' },
/*
** Global CSS
*/
css: [
],
/*
** Plugins to load before mounting the App
*/
/*
** Nuxt.js modules
*/
modules: [
// Doc: https://github.com/nuxt-community/axios-module#usage
'#nuxtjs/axios',
'nuxt-stripe-module'
],
stripe: {
version: 'v3',
publishableKey: 'pk_test_XXX',
},
/*
** Axios module configuration
*/
axios: {
// See https://github.com/nuxt-community/axios-module#options
},
/*
** Build configuration
*/
build: {
/*
** You can extend webpack config here
*/
publicPath: '/public/',
vendor: [],
extractCSS: true,
bable: {
presets: [
'es2015',
'stage-8'
],
plugins: [
['transform-runtime', {
'polyfill': true,
'regenerator': true
}]
]
},
extend (config, { isDev }) {
if (isDev && process.client) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
}
},
router: {
middleware: 'router-auth'
}
},
plugins: [
{ src: '~/plugins/fireauth', ssr: true }
]
}
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const createStore = () => {
return new Vuex.Store({
state: () => ({
counter: 0
}),
actions: {
incrementCounterUp () {
this.commit('increment')
}
},
getters: {
counter: state => state.counter
},
mutations: {
increment (state) {
state.counter++
}
}
})
}
export default createStore
At the end of the day, I was not able to identify exactly what in my application was the error.
I assume that my during my initialization, configuration or development I touched something that should not have been touched, installed something that should not have be installed, messed with a package I should not have or was to bold in my nuxt.config.js changes.
I created a new nuxt app following the same install instructions. https://nuxtjs.org/guide/installation/
Moved the above _id.vue component exactly as it is and once I got dependencies updated it worked perfectly as seen in the image below.
Thank you very much #Boussadjra Brahim, #xaviert, #Andrew1325 for you assistance.