@danimohamadnejad Can you post some code?
Tinymce vue editor does not work on second modal
Hi. Maybe I should not ask this question here. I am developing an application with laravel and vue and am using tinymce vue component in combination with bootstrap modal. First time I show modal I can click editor zone and edit but when I close modal and open again I cannot event focus on editor zone It just does nothing. Can any body help with please? thank you in advance
@lbecket Yes thank you. following is my modal and a form inside it usign my editor component (which is still a component I have created)
<template>
<div>
<b-modal size='lg' v-model='show_modal' hide-footer @hidden='cancel'>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<form @submit.prevent="submit">
<b-row>
<b-colxx sm='6' v-for='input,index in text_inputs' :key="index">
<b-form-group :label="input_label(input)">
<b-form-input v-model.trim="input.value"></b-form-input>
<div class="text-danger my-2" v-if='errors[index]'>{{errors[index]}}</div>
</b-form-group>
</b-colxx>
</b-row>
<b-row>
<b-colxx sm='12' v-for='input,index in editor_inputs' :key="index">
<b-form-group :label="input_label(input)">
<editor v-model='input.value' :config="input.config"/>
<div class="my-2 text-danger" v-if='errors[index]'>{{errors[index]}}</div>
</b-form-group>
</b-colxx>
</b-row>
<b-button type='submit' variant="primary">{{$t('posts.update-button-text')}}</b-button>
</form>
</div>
</div>
</div>
</div>
</b-modal>
</div>
</template>
<script>
import editor from "@/components/Common/editor"
export default {
components:{
editor
},
props:{
data:{
type:Object,
required:true,
},
errors:{
type:Object,
default(){
return {};
}
}
},
emits:['on_cancel', 'on_update'],
data(){
return {
show_modal:true,
inputs:{
id:{type:'hidden',value:''},
title:{type:'text',value:'', required:true, label:'posts.title'},
slug:{type:'text',value:'',required:true, label:"posts.slug"},
long_desc:{type:'editor', ref:'short_desc_ref', value:'',
label:'posts.long-desc', config:this.editor_config()},
},
dani:null,
}
},
created(){
this.fill_inputs();
},
computed:{
text_inputs(){
var out = {};
for(var i in this.inputs){
if(this.inputs[i].type=='text'){
out[i] = this.inputs[i];
}
}
return out;
},
editor_inputs(){
var out = {};
for(var i in this.inputs){
if(this.inputs[i].type=='editor'){
out[i] = this.inputs[i];
}
}
return out;
}
},
methods:{
cancel(){
this.$emit('on_cancel');
},
editor_config(){
return {
images_upload_url:route('post.image_upload'),
};
},
input_label(input){
var out = this.$t(input.label);
if(input.required){
out+=" *";
}
return out;
},
fill_inputs(){
for(var i in this.data){
if(this.inputs[i]!=undefined){
this.inputs[i].value = this.data[i];
}
}
}
}
}
</script>
and this is my editor component which is using tinymce Editor (I have renamed it to editor you can consider it Editor)
<template>
<editor ref='editor' :api-key="api_key" :value="value" @input="update_value"
:init="editor_config"/>
</template>
<script>
import Editor from "@tinymce/tinymce-vue"
import {tinymce_api_key} from "@/constants/config"
import axios from 'axios'
export default {
data(){
return {
default_plugins:['image'],
api_key:"",
editor_ref: null,
}
},
updated(){
if(editor_ref==null){
this.editor_ref = this.$refs.editor;
console.log(this.editor_ref)
}
},
components:{
editor:Editor,
},
props:{
image_types:{
type:Array,
default(){
return ['image/jpg', 'image/png', 'image/jpeg'];
},
},
value:{
type:String,
},
config:{
required:true,
type:Object
},
upload_url:{
type:String,
default:"",
}
},
created(){
this.api_key=tinymce_api_key;
},
computed:{
editor_config(){
var config = Object.assign({}, this.config);
config.plugins = this.default_plugins;
config.images_upload_handler = this.upload_image;
return config;
}
},
methods:{
update_value(value){
this.$emit('input', value);
},
upload_image(blobinfo, success, failure){
const file = blobinfo.blob();
if(!this.image_types.includes(file.type)){
alert("please select a "+this.image_types.join(",")+" file")
}else{
var data = new FormData();
data.set('file', file);
axios.post(this.config.images_upload_url, data).then((res)=>{
res = res.data;
if(!res.flag && res.msg){
failure(res.msg);
}else if(res.location){
success(res.location);
}
});
}
}
}
}
</script>
@danimohamadnejad Your modal is visible when show_modal is true, which is the case by default, but I'm not seeing anything in your code that would cause this value to become true again when you want to reopen the modal.
@lbecket thank you for your time. Please note that show_modal is always true because the containing modal is being opened conditionaly inside following page which is posts/create page. It is a vue file:
<template>
<div>
<loading-spinner v-if='processing' :fs="1"></loading-spinner>
<edit-modal v-if="edit_data && edit_data.id" :data="edit_data"
:errors="edit_errors" @on_update="update_row" @on_cancel="cancel_edit"></edit-modal>
<b-row>
<b-colxx xxs="12">
<piaf-breadcrumb :heading="$t('posts.management')" />
<div class="separator mb-5"></div>
</b-colxx>
</b-row>
<b-row>
<b-col class="col-lg-10 col-md-10">
<div class="card">
<div class="card-body">
<div class="">
<h2 class="card-title">{{$t('posts.list-title')}}</h2>
</div>
<b-alert @dismissed="clear_msg()" class='my-2' v-if='status.msg.length'
dismissible :show="status.msg.length" :variant="status.flag ?
'success':'danger'">
{{status.msg}}
</b-alert>
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>#</th>
<th>{{$t('posts.title')}}</th>
<th>{{$t('posts.slug')}}</th>
<th>{{$t('posts.meta-desc')}}</th>
<th>{{$t('posts.meta-focal')}}</th>
<th>{{$t('posts.keywords')}}</th>
<th>{{$t('created-at')}}</th>
<th>{{$t('last-modified-at')}}</th>
<th>
{{$t('quick-edit-text')}}
</th>
<th>
{{$t('delete-text')}}
</th>
</tr>
</thead>
<div v-if='data.length==0'>
<div class="text-center">
{{$t('posts.empty-list')}}
</div>
</div>
<tbody v-else>
<template v-for="d,index in data">
<show-row :editable='true' :deletable='true' :key="index"
:index="data_row_number((index+1))" :data="d"
@on_edit_mode="enable_edit_mode" @on_delete="delete_row">
</show-row>
</template>
</tbody>
</table>
</div>
</div>
</div>
<div class="card my-2" v-if='data.length && links.length'>
<div class="card-body">
<pagination :links = "links" @on_paginate="load_data"/>
</div>
</div>
</b-col>
</b-row>
</div>
</template>
<script>
import spinner from "@/components/Common/LoadingSpinner"
import showrow from "@/components/posts/table/showrow"
import pagination from '@/components/Common/pagination'
import editmodal from "@/components/posts/editmodal"
export default {
components:{
'loading-spinner':spinner,
'show-row':showrow,
'edit-modal':editmodal,
pagination
},
data(){
return {
status:{
flag:false,
msg:'',
},
show_edit_modal:true,
data_url:"",
default_query:{rels:'au;c',},
processing:0,
data:[],
links:[],
current_page:1,
per_page:1,
categories:[],
edit_data:{},
edit_errors:{},
}
},
created(){
this.data_url = route('post.search');
this.load_data(this.data_url, this.default_query);
this.load_categories()
},
methods:{
toggle_processing(processing){
this.processing = processing
},
data_row_number(index){
return ((this.current_page - 1)*this.per_page+index);
},
load_data(url, query){
this.toggle_processing(1)
const this2=this;
this.$store.dispatch('search_posts', {url, query}).then((res)=>{
this2.current_page = res.meta.current_page;
this2.per_page = res.meta.per_page;
this2.data = res.data.data
this2.links = res.meta.links;
this.toggle_processing(0);
});
},
load_categories(){
const this2=this;
this.$store.dispatch('get_all_categories').then((res)=>{
if(res.data){
this2.categories = this.categories;
}
})
},
enable_edit_mode(data_object){
this.edit_data = data_object;
return this;
},
delete_row(data_object){
},
update_row(data_object){
const this2=this;
this.$store.dispatch('update_post', data_object).then((res)=>{
console.log(res);
})
},
cancel_edit(){
this.edit_data = {};
}
}
}
</script>
please note when I click on edit button of one of data rows then edit_data property will be that data object and we display modal using (v-if) and inside then modal we can click cancel button to call cancel_edit method of this page and modal will hide or remove
@danimohamadnejad OK, it wasn't immediately clear that you were talking about a modal within a modal.
Am I correct in assuming that it's the edit-modal component that is not appearing? It looks like the visibility is dependent on the data_object parameter that you're accepting in your enable_edit_mode method.
When you call it here:
@on_edit_mode="enable_edit_mode"
you're not passing a parameter and so data_object in the method is undefined, which means that this.edit_data is being assigned an undefined value when I believe you want true
@lbecket Sorry I think you misunderstood whole process! I have post manage page, inside page I have an edit modal which is opened when "edit" button is clicked in one of data rows (show-row component). Then modal pop up. now I can see modal and use Tinymce editor and use it but when I hide modal and open it again using one of "edit" buttons then I still can see edit modal buut I can not use tinymce I cannot interact with it I cannot focus on it I dont know how to fix this problem. thank you again for your time
@danimohamadnejad OK, I'm finally following along.
Is it possible that closing the modal the first time is wiping out the api_key? I see that you're assigning that when the component is created, but if it's somehow getting wiped when the modal is closed, then that might explain why the functionality is missing when opened a second time.
@lbecket No I can use editor without api key too. I have seen from posts on stackoverflow and other places that possible solution is to say something like tinymce.remove('element-selector'); but I dont know how to do that on tiny vue component
@danimohamadnejad Sorry, man, I don't have direct experience with tinymce. Sounds like you're on the right track with that, though.
@lbecket Thank you for your patience. Good luck
@danimohamadnejad did you find a solution to this? I'm experiencing the same thing
Please or to participate in this conversation.