I am editing ckeditor5 config, and I need to add custom class to table. What I tried:
ckeditorConfigRegistry.add(config => ({
toolbar: [...config.toolbar, 'fontColor', 'fontBackgroundColor'],
table: {
customClass: ["table", "table-bordered"]
}
}));
also tried:
table: {
class: "table table-bordered"
}
and:
table: {
attributes: {
class: "table table-bordered"
}
}
Any ideas how to add class to table element in config?
Related
Background: Trying to use ckeditor5 as a replacement for my homegrown editor in a non-invasive way - meaning without changing my edited content or its class definitions. Would like to have WYSIWYG in the editor. Using django_ckeditor_5 as a base with my own ckeditor5 build that includes ckedito5-inspector and my extraPlugins and custom CSS. This works nicely.
Problem: When I load the following HTML into ClassicEditor (edited textarea.value):
<p>Text with inline image: <img class="someclass" src="/media/uploads/some.jpeg"></p>
in the editor view area, browser-inspection of the DOM shows:
...
<p>Text with an inline image:
<span class="image-inline ck-widget someclass ck-widget_with-resizer" contenteditable="false">
<img src="/media/uploads/some.jpeg">
<div class="ck ck-reset_all ck-widget__resizer ck-hidden">
<div ...></div></span></p>
...
Because the "someclass" class has been removed from and moved to the enclosing class attributes, my stylesheets are not able to size this image element as they would appear before editing.
If, within the ckeditor5 view, I edit the element using the browser inspector 'by hand' and add back class="someclass" to the image, ckeditor5 displays my page as I'd expect it with "someclass" and with the editing frame/tools also there. Switching to source-editing and back shows the class="someclass" on the and keeps it there after switching back to document editing mode.
(To get all this, I enabled the GeneralHtmlSupport plugin in the editor config with all allowed per instructions, and that seems to work fine.) I also added the following simple plugin:
export default class Extend extends Plugin {
static get pluginName() {
return 'Extend';
}
#updateSchema() {
const schema = this.editor.model.schema;
schema.extend('imageInline', {
allowAttributes: ['class']
});
}
init() {
const editor = this.editor;
this.#updateSchema();
}
}
to extend the imageInline model hoping that would make the Image plugin keep this class attribute.
This is the part where I need some direction on how to proceed - what should be added/modified in the Image Plugin or in my Extend plugin to keep the class attribute with the element while editing - basically to fulfill the WYSIWYG desire?
The following version does not rely on GeneralHtmlSupport but creates an imageClassAttribute model element and uses that to convert only the image class attribute and place it on the imageInline model view widget element.
import Plugin from '#ckeditor/ckeditor5-core/src/plugin';
export default class Extend extends Plugin {
static get pluginName() {
return 'Extend';
}
#updateSchema() {
const schema = this.editor.model.schema;
schema.register( 'imageClassAttribute', {
isBlock: false,
isInline: false,
isObject: true,
isSelectable: false,
isContent: true,
allowWhere: 'imageInline',
});
schema.extend('imageInline', {
allowAttributes: ['imageClassAttribute' ]
});
}
init() {
const editor = this.editor;
this.#updateSchema();
this.#setupConversion();
}
#setupConversion() {
const editor = this.editor;
const t = editor.t;
const conversion = editor.conversion;
conversion.for( 'upcast' )
.attributeToAttribute({
view: 'class',
model: 'imageClassAttribute'
});
conversion.for( 'dataDowncast' )
.attributeToAttribute({
model: 'imageClassAttribute',
view: 'class'
});
conversion.for ( 'editingDowncast' ).add( // Custom conversion helper
dispatcher =>
dispatcher.on( 'attribute:imageClassAttribute:imageInline', (evt, data, { writer, consumable, mapper }) => {
if ( !consumable.consume(data.item, evt.name) ) {
return;
}
const imageContainer = mapper.toViewElement(data.item);
const imageElement = imageContainer.getChild(0);
if ( data.attributeNewValue !== null ) {
writer.setAttribute('class', data.attributeNewValue, imageElement);
} else {
writer.removeAttribute('class', imageElement);
}
})
);
}
}
Well, Mr. Nose Tothegrind found two solutions after digging through ckeditor5 code, here's the first one. This extension Plugin restores all image attributes that are collected by GeneralHtmlSupport. It can be imported and added to a custom ckeditor5 build app.js file by adding config.extraPlugins = [ Extend ]; before the editor.create(...) statement.
import Plugin from '#ckeditor/ckeditor5-core/src/plugin';
import GeneralHtmlSupport from '#ckeditor/ckeditor5-html-support/src/generalhtmlsupport';
export default class Extend extends Plugin {
static get pluginName() {
return 'Extend';
}
static get requires() {
return [ GeneralHtmlSupport ];
}
init() {
const editor = this.editor;
this.#setupConversion();
}
#setupConversion() {
const editor = this.editor;
const t = editor.t;
const conversion = editor.conversion;
conversion.for ( 'editingDowncast' ).add( // Custom conversion helper
dispatcher =>
dispatcher.on( 'attribute:htmlAttributes:imageInline', (evt, data, { writer, mapper }) => {
const imageContainer = mapper.toViewElement(data.item);
const imageElement = imageContainer.getChild(0);
if ( data.attributeNewValue !== null ) {
const newValue = data.attributeNewValue;
if ( newValue.classes ) {
writer.setAttribute('class', newValue.classes.join(' '), imageElement);
}
if ( newValue.attributes ) {
for (const name of Object.keys(newValue.attributes)) {
writer.setAttribute( name, newValue.attributes[name], imageElement);
}
}
} else {
writer.removeAttribute('class', imageElement);
}
})
);
}a
}
I am using Vuejs and have, inside a form, a textarea field.
When editing i can not see the value, inside the textarea.
If i save i do not lose the previous information as expected.
If i edit it stores the data as expected.
I only can not find, how to present the textarea value, when editing.
Inside a v-for loop i have the textarea that extendes a parent textarea template :
<row v-for="(field, index) in fields" :key="index">
<div v-if="field.formType === 'textarea'">
<va-textarea
:id="field.index"
v-model='formInput[index]'
v-bind:value="formValue[index]"
></va-textarea>
The field is defined in the data property :
data () {
return {
fields: {
Commentts: {
label : 'Commentts',
sortable : false,
type : 'textarea',
formType : 'textarea',
formReadOnly : false
}
And i have the formSave method to insert or edit:
methods: {
formSave() {
if ( this.formValue.Id === undefined) {
this.formInput.Motivo_Id = this.formInput.Motivo.id
}
this.saveButton = true;
this.formLoading= true;
this.axios.post('Courses/save',
{
"data": { Id : this.formValue.Id,
Date : this.saveDateTime(this.formInput.Date),
faculty_Id: this.formInput.faculty_Id,
Commentts: this.formInput.Commentts
},
"route" : this.$route.name,
}).then((response) => {
How can i show the textarea information when editing the form ?
Looks strange but let's figure out.
Loop
<row v-for="(field, index) in fields" :key="index">
By your example fields is the object and variable index contains value "Commentts" and not an index. Is it what you want?
Data propagation
<va-textarea
:id="field.index"
v-model='formInput[index]'
v-bind:value="formValue[index]"
></va-textarea>
I know nothing about va-textarea component implementation but I hope parameters v-model and :value were configured properly.
And with current implementation component's data field must contain and:
data () {
return {
fields: {
Commentts: {
.....
},
formInput: {
Commentts: ...some data...
},
formValue: {
Commentts: ...some data...
},
Because declaration `v-model='formInput[index]'` requires `formInput` field in the root of the data field with `Commentts` inside.
I want to display the user name instead supervisor_id in the table list in Vue.js. this is one to many relationship. supervisor_id is foreign key from user table.
/// this is view in vue.js. I want to to change work.supervisor_id into something like work.user.name, but it do not work.
<tr v-for="(work,index) in works.data" :key="work.work_id">
<td>{{index+1}}</td>
<td>{{work.work_name}}</td>
<td>{{work.supervisor_id}}</td>
<td>{{work.payment}}</td>
<td>{{work.created_at | myDate}}</td>
<td>{{work.end_date}}</td>
<td>{{work.worker_id}}</td>
<td>
/// this is my script in vue.js
<script>
export default {
data() {
return{
editmode: false,
works:{},
index:1,
users:{},
form: new Form({
work_id:'',
work_name:'',
description:'',
payment:'',
location:'',
end_date:'',
worker_id:'',
application_status:'New',
supervisor_id:'',
})
}
},
methods:{
getResults(page = 1) {
axios.get('api/work?page=' + page)
.then(response => {
this.works = response.data;
});
},
loadWork(){
if(this.$gate.isClerk()){
// axios.get('api/work').then(({data})=>(this.works = data));
axios.get('api/work').then(response => (this.works = response.data));
}
},
/// this is my work controller
public function index()
{
return Work::latest()->paginate(10);
}
the data in the vue.js devtool
For this to work, it would require the a relationship on the Work model which returns the supervisor record which you require.
This will allow you to get the supervisor's (or user's depending on the relationship) name.
Work Model (app\Work.php):
public function supervisor()
{
return $this->hasOne(User::class, 'supervisor_id');
}
Now in your controller, you can use the ->with() eloquent method to eager load a relation:
public function index()
{
return Work::with('supervisor')->latest()->paginate(10);
}
You should now be able to access the supervisor name within vue using:
{{ work.supervisor.name }}
I hope this helps.
I made a bar column chart using ExtJs mvc. Now in the controller I want to add a function for click event to catch the selected value of the column. Here is my controller code:
Ext.define('Gamma.controller.ControlFile', {
extend : 'Ext.app.Controller',
//define the stores
stores : ['BarColumn','RadarView','VoiceCallStore','SMSCallStore','MMSCallStore','GPRSUsageStore'],
//define the models
models : ['BarCol','radar','VoiceCallModel','SMSCallModel','MMSCallModel','GPRSUsageModel'],
//define the views
views : ['BarColumnChart','LineChart','RadarChart','VoicePie','SMSPie','MMSPie','GPRSPie'],
init : function() {
this.control({
});
}
});
Please any one help me.
On chart:
listeners : {
itemmousedown : function(obj) {
this.fireEvent('itemmousedownchartbar',obj);
}
}
At final on chart defined, after this.CallParent():
this.addEvents('itemmousedownchartbar');
Now, on Controller:
'barChartView' : {
itemmousedownchartbar: this.function_to_call
}
I have a checkitem menu and I want to add icons to each menu item, so I inserted each icon after the menu item is rendered.
peace of my code:
{ xtype: 'menucheckitem',
text: 'First Arrow'
listeners: {
render: {
fn: me.onMenucheckitemRender,
scope: me
}
}
}
onMenucheckitemRender: function (abstractcomponent, options)
{
Ext.DomHelper.insertAfter(abstractcomponent.getEl().down(".x-menu-item-icon"), {
tag: 'img',
src: "icons/arrow1.png"
});
}
This works just fine, but since I will need it many times with different icons, I would like to know how to create a subclass so I can reuse this functionality.
Thank you
use the Ext.define method and the extend property.
Ext.define('SomeNamespace.menu.menucheckitemWithIcon', {
extand: 'Ext.menu.CheckItem',
alias: 'widget.menucheckitemWithIcon',
.
.
.
});