Customize vue2-editor toolbar - vue.js

This is the dependency I'm using for the editor and they have an example where they modify the default toolbar to remove certain options, I would like to remove some options but the example is very lacking and doesn't show how to add all the options I would like and I don't know how to add them.
This is the example from the dependency page
<template>
<div id="app">
<vue-editor v-model="content" :editorToolbar="customToolbar"></vue-editor>
</div>
</template>
<script>
import { VueEditor } from "vue2-editor";
export default {
components: {
VueEditor
},
data() {
return {
content: "<h1>Html For Editor</h1>",
customToolbar: [["bold", "italic", "underline"], [{ list: "ordered" }, { list: "bullet" }], ["image", "code-block"]]
};
}
};
</script>
I would like in my toolbar something like this
customToolbar: [["bold", "italic", "underline"], [{ list: "ordered" }, { list: "bullet" }],
[{ align: "left" }, { align: "center" }, { align: "right"}, { align: "justify"}],
[{ color: "color-picker" }]],
However this is the result, the align: left is not showing up and the color: color-picker doesn't work. If I click on the color picker nothing happens and no menu shows up
I'm not sure how I could get this to work
This is the CodeSandBox my current setup that doesn't work

Using the following configuration should fix the issues:
customToolbar: [
["bold", "italic", "underline"],
[{ list: "ordered" }, { list: "bullet" }],
[
{ align: "" },
{ align: "center" },
{ align: "right" },
{ align: "justify" }
],
[{ color: [] }]
]
Here is the code for the standard configuration of the toolbar:
https://github.com/davidroyer/vue2-editor/blob/master/src/helpers/default-toolbar.js

Related

How can I customize vue2-editor toolbar?

I wrapped VueEditor component and followed what was written here to add font family selection to my toolbar.
<template>
<VueEditor
v-bind="$attrs"
v-on="$listeners"
:editor-toolbar="customToolbar"
/>
</template>
<script>
import { VueEditor, Quill } from 'vue2-editor'
const fonts = Quill.import('formats/font')
export default {
components: {
VueEditor
},
data () {
return {
customToolbar: [
[
{ header: [false, 1, 2, 3, 4, 5, 6] }
],
['bold', 'italic', 'underline', 'strike'],
[
{ 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'],
[
{ font: fonts.whitelist }
]
]
}
}
}
</script>
I have several questions:
How can I change font family selection position? I want to have it right after heading selection.
Why do I only have two font families available? (Serif and Monospace)
How can I add font size selection to my toolbar?

How do you output the HTML from GrapesJs in a VueJS application?

I have set up a VueJS application including GrapesJS using grapesjs & grapesjs-preset-webpage. The editor works perfectly, but I cannot see in the documentation how to render just the HTML created by the editor without the editor controls being present.
The editor displays this, which is perfect for a CMS when in editor mode :
However, I wish to be able to display the result of the editor design as a finished webpage like this:
It is not clear to me from the GrapesJS documentation how this would be achieved in a VueJS application??
My code is:
<template>
<div>
<div id="gjs"></div>
</div>
</template>
<script>
import grapesjs from 'grapesjs'
import 'grapesjs/dist/css/grapes.min.css'
import 'grapesjs/dist/grapes.min.js'
import 'grapesjs-preset-webpage/dist/grapesjs-preset-webpage.min.css'
import 'grapesjs-preset-webpage/dist/grapesjs-preset-webpage.min.js'
export default {
name: 'WebBuilder',
mounted(){
grapesjs.init({
container: '#gjs',
height: '100vh',
width: '100%',
plugins: ['gjs-preset-webpage'],
storageManager: {
id: 'gjs-',
type: 'local',
autosave: true,
storeComponents: true,
storeStyles: true,
storeHtml: true,
storeCss: true,
},
deviceManager: {
devices:
[
{
id: 'desktop',
name: 'Desktop',
width: '',
},
{
id: 'tablet',
name: 'Tablet',
width: '768px',
widthMedia: '992px',
},
{
id: 'mobilePortrait',
name: 'Mobile portrait',
width: '320px',
widthMedia: '575px',
},
]
},
pluginsOpts: {
'grapesjs-preset-webpage': {
blocksBasicOpts: {
blocks: ['column1', 'column2', 'column3', 'column3-7', 'text', 'link', 'image', 'video'],
flexGrid: 1,
},
blocks: ['link-block', 'quote', 'text-basic'],
},
}
})
},
}
</script>

Vue Draggable Recursive / Nested Dragging Weird Behavior

This question will be bountied as soon as I can, so a big rep reward coming to someone!
EDIT: One more layer to this issue I noticed, The lowest level children when I try to drag it somewhere else it doesn't work, acts like it will but goes back where it was (i.e it's children are empty). But when I drag the parent of a child somewhere else it does one of the following:
Moves the parent and it's parent somewhere else where I drag it, but leaves the child where it was i.e
Initial state on a refresh
After I drag col-2 to container-1
or
Moves the child into the container where I dragged the parent to but leaves the parent where it was i.e
Initial state on a refresh
After dragging col-2 into col-1
Original Post
Hey guys, been building a landing page builder and decided vue-draggable would be a nice addition. That said after 3 days of headaches trying to make this work I'm at a loss. So far I've followed the nested example guide which has been KINDA working, in addition, I followed an issue about the nested guide on here adding an emitter to the children for proper updates. Now my getters and setters are firing BUT I'm still having a problem dragging elements(see the video)
http://www.giphy.com/gifs/ZMiyi8LEcI73nye1ZN
As you can see when I drag stuff around it's strange behavior:
Example cases:
When I drag col 2 label into col 1 it moves the children inside into
col one, does not change col 2s place
When I drag paragraph label
anywhere it will not move, shows like it will but when I release
nothing happens
If I drag row 1 from the original starting state you
saw in the gif into the paragraph I end up with the following:
Just 3 sample cases, references:
https://sortablejs.github.io/Vue.Draggable/#/nested-with-vmodel
https://github.com/SortableJS/Vue.Draggable/issues/701#issuecomment-686187071
my code creating these results:
component-renderer.vue (THERE'S A NOTE IN HERE TO READ)
<draggable
v-bind="dragOptions"
:list="list"
:value="value"
style="position: relative; border: 1px solid red"
:tag="data.tagName"
:class="data.attributes.class + ` border border-danger p-3`"
#input="emitter"
#change="onChange" //NOTE: I've tried setting the group here to row instead of in the computed prop below, didn't work
>
<slot></slot>
<component-renderer
v-for="el in realValue"
:key="el.attributes.id"
:list="el.children"
:data="el"
:child="true"
#change="onChange"
>
<span style="position: absolute; top: 0; left: 0; background: red">{{
`${el.tagName} - ${el.attributes.id}`
}}</span>
{{ el.textNode }}
</component-renderer>
</draggable>
</template>
<script>
import draggable from "vuedraggable";
export default {
name: "ComponentRenderer",
components: {
draggable,
},
props: {
data: {
required: false,
type: Object,
default: null,
},
value: {
required: false,
type: Array,
default: null,
},
list: {
required: false,
type: Array,
default: null,
},
child: {
type: Boolean,
default: false,
required: false,
},
},
computed: {
dragOptions() {
return {
animation: 0,
disabled: false,
ghostClass: "row",
group: "row",
};
},
realValue() {
return this.value ? this.value : this.list;
},
},
methods: {
emitter(value) {
this.$emit("input", value);
},
onChange: function () {
if (this.child === true) {
this.$emit("change");
} else {
this.emitter(this.value);
}
},
},
};
</script>
<style scoped></style>
PageEditor.vue:
<div id="wysiwyg-page-editor">
<ChargeOverNavBar />
<div class="editor">
<ComponentRenderer v-model="elements" :data="elements[0]" />
</div>
<ChargeOverFooter />
</div>
</template>
<script>
import ChargeOverNavBar from "#/components/ChargeOverNavBar";
import ChargeOverFooter from "#/components/ChargeOverFooter";
import InlineEditor from "#ckeditor/ckeditor5-build-inline";
import ComponentRenderer from "#/components/module-editor/ComponentRenderer";
export default {
name: "PageEditor",
components: {
ComponentRenderer,
ChargeOverFooter,
ChargeOverNavBar,
},
data() {
return {
editor: InlineEditor,
editorConfig: {},
activeSection: null,
page: {},
panels: {
pageProperties: true,
seoProperties: true,
sectionProperties: false,
},
};
},
computed: {
elements: {
get() {
console.log("getter");
return JSON.parse(JSON.stringify(this.$store.state.editor.editorData));
},
set(value) {
console.log("setter");
this.$store.dispatch("setEditor", value);
},
},
},
};
</script>
<style lang="scss" scoped>
#use "../assets/scss/components/PageEditor";
</style>
editor.js(store module):
state: {
editorData: [],
editorLoading: false,
},
mutations: {
SAVE_EDITOR(state, data) {
state.editorData = data;
},
TOGGLE_EDITOR_LOAD(state, busy) {
state.editorLoading = busy;
},
},
actions: {
setEditor({ commit }, data) {
commit("SAVE_EDITOR", data);
},
loadEditor({ commit }) {
commit("TOGGLE_EDITOR_LOAD", true);
//TODO: Change me to read API DATA
let fakeData = [
{
tagName: "section",
attributes: {
id: "section-1",
class: "test",
},
children: [
{
tagName: "div",
attributes: {
id: "container-1",
class: "container",
},
children: [
{
tagName: "div",
attributes: {
id: "row-1",
class: "row",
},
children: [
{
tagName: "div",
attributes: {
id: "col-1",
class: "col",
},
children: [],
},
{
tagName: "div",
attributes: {
id: "col-2",
class: "col",
},
children: [
{
tagName: "p",
attributes: {
id: "p-1",
class: "p",
},
textNode: "This is my paragraph",
children: [],
},
],
},
],
},
],
},
],
},
];
commit("SAVE_EDITOR", fakeData);
commit("TOGGLE_EDITOR_LOAD", false);
},
},
getters: {
getEditorData: (state) => state.editorData,
getEditorLoading: (state) => state.editorLoading,
},
};
It seems only dragging labels works for moving stuff around but not like i'd expect. I think this makes sense but why can't I drag the body anywhere? It's not slotted in header or footer and the docs says that's the onlytime it wouldn't be? Can I not use as the tag itself and drag it?
As I'm sure all of you can deduce the behavior I'm expecting, anything should be draggable into any section(in the future I want this to change so only cols can be dragged into rows, rows can only be dragged into sections etc(but for now I'm not sure how to do this so we start at the beginning :D)).
Also yes I know those components are kinda messy atm, until I fix this I'm not cleaning them up as I keep drastically changing the contents of these files trying to make it work, sorry it's hacky atm!
Any help or ideas would be amazing!
Thanks guys!

Create highcharts vue component

in my page i need to show many charts, so i would like to create an Highcharts component and use it inside my .vue file within a v-for cicle.
how could i achieve this? here is what i did:
in my .vue page I have:
<v-flex ma-3 v-for="(el,index) in Items">
<my-chart-component
:series="el.series"
:xlabels="el.Labels"
:height="'300px'"
width="100%"
></my-chart-component>
</v-flex>
inside my component i have:
<template>
<chart
:series="mySeries"
:xlabels="myXlabels"
:options="myChartOptions"
:height="height"
width="100%"
></chart>
</template>
<script>
import VWidget from '#/components/VWidget';
import {Chart} from 'highcharts-vue'
import Highcharts from 'highcharts/highcharts';
import loadExporting from 'highcharts/modules/exporting';
import brokenAxis from 'highcharts/modules/broken-axis';
export default {
name: 'my-chart-component',
components: {
VWidget,
Chart,
Highcharts,
loadExporting,
brokenAxis,
},
props: {
mySeries:Array,
myXlabels:Array,
height:String
},
data() {
return {
myChartOptions: {
chart: {
type: 'column'
},
legend: {
align: 'left',
verticalAlign: 'top',
layout: 'vertical',
x: 100,
y: 30,
floating: true
},
navigation: {
buttonOptions: {
enabled: true
}
},
credits: {
enabled: false
},
xAxis: {
xAxis: {
categories: props.myXlabels
},
},
yAxis: [{
title: {
text: '%',
align: 'middle',
rotation: 0,
},
type: 'linear',
}],
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
}
},
series: {
pointWidth: 15,
borderWidth: 0,
dataLabels: {
enabled: false,
format: '{point.y:.0f}%'
},
cursor: 'pointer',
point: {
events: {
click: ''
}
}
}
},
exporting: {
sourceWidth: 1000,
sourceHeight: 600,
},
tooltip: {
shared: true,
valueSuffix: ' %',
followPointer: false,
},
title: {
text: '',
align: 'left',
margin: 30
},
colors: [
'#00c104',
'#d45087',
],
series: props.mySeries
},
};
},
created(){
loadExporting(Highcharts);
},
methods: {
}
};
</script>
now, i have many errors in the console, i have this error:
Error in data(): "ReferenceError: props is not defined"
in
at src/components/MyChartComponent.vue
and then [Vue warn]: Property or method "myChartOptions" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property
it seems i can't pass the chartOptions by props, how can i workaround this?
thank you
The props that you are passing to your child component should be named as props in the child component.
If props are called mySeries, myXlabels and height, than you should pass it like :my-series, :my-xlabels and :height.
<v-flex ma-3 v-for="(el,index) in Items">
<my-chart-component
:my-series="el.series"
:my-xlabels="el.Labels"
:height="'300px'"
width="100%"
></my-chart-component>
</v-flex>
need to define
<script>
export default {
props: {
Items: Array,
},
}
</script>
then need to pass your variable from parent vue page into this page or component:
<MegaMenu :categories="categories"/>

Why echarts are not showing on I.E-11 version

I had created a project using vuejs+Vue-CLI and integrated echarts in it. Echarts are working well in all browsers but when I open it in IE-11 version, page can't load and it shows following error:
[object Error]{description: "Expected ')'", message: "Expected ')'", name: "SyntaxError", number: -2146827282, stack: "SyntaxError...", Symbol()_n.kyufm4c0tec: undefined, Symbol()_p.kyufm4c0tec: undefined, Symbol()_q.kyufm4c0tec: undefined, Symbol()_r.kyufm4c0tec: undefined, Symbol(Lang fallback)_m.kyufm4c0tec: undefined, Symbol(util.promisify.custom)_o.kyufm4c0tec: undefined}
Here is my code:
<template>
<ECharts :options="pie" style="width:300px; height:260px">
</ECharts>
</template>
<script>
import ECharts from "vue-echarts/components/ECharts.vue";
import "echarts/lib/chart/pie";
import "echarts/lib/component/title";
export default {
components: {
ECharts
},
data() {
return {
pie: {
backgroundColor: "transparent",
tooltip: {
trigger: "item",
formatter: "{a} <br/>{b} : {c} ({d}%)"
},
series: [{
name: "Product Sales",
type: "pie",
radius: ["50%", "70%"],
avoidLabelOverlap: false,
data: [{
value: 1,
name: "Product A"
},
{
value: 2,
name: "Product B"
},
{
value: 3,
name: "Product C"
}
],
label: {
normal: {
show: false,
position: "center"
},
emphasis: {
show: true,
textStyle: {
fontSize: "20",
fontWeight: "bold"
}
}
},
labelLine: {
normal: {
show: false
}
}
}]
}
};
}
};
</script>
what's an issue in IE browser I also searched for the solution and tried it but did't get the result.
Versions:
echarts-4.1.0,
vue-echarts: 3.1.1
Any help will be appreciated! Thanks
The documentation of vue-echarts-v3 does not inform it, but you have to add the echarts on your webpack (or any other bundler you are using) configuration as well.
{
test: /\.js$/,
loader: 'babel-loader',
include: [
resolve('src'),
resolve('test'),
resolve('node_modules/vue-echarts-v3/src'), // Their suggestion https://www.npmjs.com/package/vue-echarts-v3
resolve('node_modules/echarts/lib'), // Not suggested, but required as well
]
},