Я использую Vue 2.X с Quill JS в проекте.
Редактор Quill находится в модуле. Однако внутри я использую прослушиватель событий, чтобы размыть сам редактор. У Quill нет размытия, и эти решения не работают.
У меня также есть привязка класса Vue к содержащему его div.
Если я вкладываюсь или щелкаю, а затем выхожу из редактора, появляется красное поле с предупреждающей меткой в соответствии с условие для привязки класса.
Размытие проверяет, ввел ли пользователь пробелы, а затем покинул редактор. Размытие очищает редактор, устанавливает для объекта данных Vue программу. Objective значение пустое, а также устанавливает для объекта данных ,nda.showErrorObjective, значение true. Он работает.
Однако класс не активируется в редакторе, даже если для его триггеров установлено значение true.
Я загрузил это в Code Pen здесь: https://codepen.io/ziggythecompace/pen/jOboRQE
Спасибо, Донна
Код также ниже.
Vue.component('editor', {
template: '<div ref="editor"></div>',
props: {
value: {
type: String,
default: ''
},
placeholder: {
type: String,
default: "Please type here."
}
},
data: function data() {
return {
editor: null
};
},
mounted: function mounted() {
var _this = this;
this.editor = new Quill(this.$refs.editor, {
modules: {
keyboard: {
bindings: {
'tab': {
key: 9,
handler: function(range, context) {
return true;
}
}
}
},
toolbar: [
['bold', 'italic', 'underline', {
'color': []
}, {
'background': []
}, {
'list': 'bullet'
}, 'link', 'clean']
]
},
theme: 'snow',
formats: ['bold', 'underline', 'italic', 'color', 'background', 'list', 'link', 'clean']
});
this.editor.root.innerHTML = this.value;
this.editor.root.dataset.placeholder = this.placeholder;
this.editor.on('text-change', function() {
return _this.update();
});
// Prevent the event listeners from bubbling up.
if (document.querySelector(".ql-toolbar")) {
document.querySelector('.ql-toolbar').addEventListener('mousedown', function(e) {
return e.preventDefault();
});
}
//The below checks to see if the editors are loaded in the DOM.
if (document.querySelector(".ql-editor")) {
document.querySelector(".ql-editor").addEventListener('blur', function() {
var lcEditor = document.querySelector(".ql-editor");
var lcInput = lcEditor.innerHTML.replace(/<(.|\n)*?>/g, '').trim();
if (lcInput.length === 0) {
lcEditor.innerHTML = '';
app.$data.agenda.objective = '';
app.$data.showErrorObjective = true;
} else {
app.$data.showErrorObjective = false;
}
console.log("showErrorObjective: " + app.$data.showErrorObjective);
});
}
},
methods: {
update: function update() {
const limit = 1000;
//console.log(this.editor.getText().length);
if (this.editor.getLength() > limit) {
this.editor.deleteText(limit, this.editor.getLength());
}
this.$emit('input', this.editor.getText() ? this.editor.root.innerHTML : '');
}
}
});
var app = new Vue({
el: '#vueApp',
data: {
agenda: {
objective: ""
},
showMeetingObjective: true,
editMeetingObjective: false,
showErrorObjective: false,
showValidationErrors: false
},
methods: {
checkTextArea: function(id) {
if (id === "objectives") {
if (this.agenda.objective.replace(/<(.|\n)*?>/g, '').trim().length === 0) {
this.agenda.objective = "";
}
}
}
}
});
.form-group {
margin-bottom: 0.25rem;
}
.agenda-label {
color: #323130;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 14px;
font-weight: 600;
line-height: 17px;
text-align: left;
}
.agendaAreaEdit {
background-color: #FFFFFF;
border: 1px solid #979797;
border-radius: 2px;
padding: 8px 8px 8px 8px;
}
.agendaAreaSmall {
color: #605E5C !important;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
font-size: 12px !important;
font-weight: 300 !important;
line-height: 14px !important;
text-align: left !important;
overflow: hidden !important;
/*height:28px;*/
max-height: 28px !important;
padding: 0px !important;
width: 100% !important;
border: none !important;
}
.agendaAreaEditor.error {
border: 1px solid #CD0A0A !important;
}
.fa-pencil {
font-size: 0.9em;
color: #0078D4;
}
.fieldWarningLabel {
background-color: #FDE7E9;
border-radius: 2px;
height: 16px;
padding: 0px 8px;
margin-bottom: 0px !important;
float: right;
color: #D13438;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 11px;
font-weight: 400;
line-height: 14.63px;
}
<link href="https://cdn.quilljs.com/1.3.4/quill.snow.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css" />
<link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
<script src="https://cdn.quilljs.com/1.3.4/quill.js"></script>
<script type="text/javascript" src="https://unpkg.com/vue@latest/dist/vue.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
<div id="vueApp" class="container">
<form id="myForm">
<div class="form-group" style="padding-top:16px;">
<div v-bind:class="{agendaAreaEdit: editMeetingObjective}">
<label class="agenda-label" for="purpose">Meeting Objective</label>
<button v-if="!showMeetingObjective && !editMeetingObjective" v-on:click="showMeetingObjective=true, editMeetingObjective=true;" href="#" type="button" class="btn btn-sm btn-min-padding pull-right"><i class="fa fa-pencil" aria-hidden="true"></i></button>
<div class="agendaAreaEditor" id="objectives" v-on:keypress="checkTextArea('objectives')" v-show="showMeetingObjective || editMeetingObjective" v-bind:class="{error: agenda.objective.trim().length===0 && (showValidationErrors || showErrorObjective)}">
<editor v-model="agenda.objective"></editor>
</div>
<!--<div v-if="agenda.objective.trim().length===0 && (showValidationErrors || showErrorObjective)">-->
<div v-if="agenda.objective.trim().length===0 && showErrorObjective">
<label class="fieldWarningLabel">Please enter in Meeting Objectives/Purpose</label>
<div style="clear:both;"></div>
</div>
<button v-if="showMeetingObjective && editMeetingObjective" v-on:click="showMeetingObjective=false, editMeetingObjective=false;" class="btn btn-sm btn-min-padding pull-right" style="margin: 8px 0px 0px 0px;" href="#" type="button"><i class="fa fa-check" aria-hidden="true"><span class="buttonText" v-html='$t("button.save")'></span></i></button>
<div style="clear:both"></div>
<div v-show="!showMeetingObjective" id="textarea" v-html="agenda.objective" class="agendaAreaSmall" style="height:24px;"></div>
</div>
</div>
</form>
</div>