Items list editor
by Soviut
HTML
<link href="https://cdnjs.cloudflare.com/ajax/libs/quill/1.3.6/quill.core.min.css" rel="stylesheet">
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
<div id="app">
<div v-for="section, i in sections">
<div class="actions">
<button class="actions__button" @click="addSection('text', i)">Add Text</button>
<button class="actions__button" @click="addSection('image', i)">Add Image</button>
</div>
<div class="section">
<header class="section__header">
<button @click="deleteSection(i)">Delete</button>
<button @click="moveSectionUp(i)" :disabled="i === 0">Move Up</button>
<button @click="moveSectionDown(i)" :disabled="i === sections.length - 1">Move Down</button>
</header>
<div class="section__body">
<template v-if="section.type === 'text'">
<div ref="editors"></div>
</template>
<template v-if="section.type === 'image'">
<img :src="section.body">
</template>
</div>
</div>
</div>
<div class="actions">
<button class="actions__button" @click="addSection('text')">Add Text</button>
<button class="actions__button" @click="addSection('image')">Add Image</button>
</div>
</div>
CSS
body {
background: #FFF;
padding: 20px;
font-family: arial, Helvetica, san-serif;
}
.section {
margin-top: 10px;
border: solid 1px #CCC;
}
.section__header {
padding: 10px;
border-bottom: solid 1px #CCC;
}
.section__body {
padding: 10px;
}
.section__body > img {
width: 100%;
}
.actions {
display: flex;
margin-top: 10px;
}
.actions__button {
display: block;
width: 100%;
padding: 10px;
border: 0;
border-radius: 4px;
background: #336699;
color: #FFF;
}
Vue
let arrayMove = (arr, from, to) => arr.splice(to, 0, arr.splice(from, 1)[0])
const editorOptions = {
theme: 'snow',
modules: {
toolbar: ['bold', 'italic', 'underline'],
}
}
new Vue({
el: "#app",
data: {
sections: [],
},
methods: {
addSection(typ, i) {
console.log(i)
let body = ''
let id = Math.abs(Math.random()).toString().replace('.', '')
if (typ === 'text') {
body = `${id} this is some text.`
}
else if (typ === 'image') {
body = `https://via.placeholder.com/350x150?text=${id}`
}
let section = {
id: id,
type: typ,
body: body
}
if (typeof i === 'undefined') {
this.sections.push(section)
}
else {
this.sections.splice(i, 0, section)
}
if (typ === 'text') {
Vue.nextTick(() => {
if (typeof i === 'undefined') {
new Quill(this.$refs.editors[this.$refs.editors.length - 1], editorOptions)
}
else {
new Quill(this.$refs.editors[i + 1], editorOptions)
}
})
}
},
deleteSection(i) {
this.sections.splice(i, 1)
},
moveSectionUp(i) {
if (i > 0) {
arrayMove(this.sections, i, i - 1)
}
},
moveSectionDown(i) {
if (i < this.sections.length - 1) {
arrayMove(this.sections, i, i + 1)
}
}
}
})