CKEditor5-Vue autosave problem. I can't call instance in autosave function - vue.js

The editor work fine except autosave.
I import autosave plugin properly,and I can receive the return data.
https://i.stack.imgur.com/cDW9x.jpg
in this case, i can receive the autosave data.
But I can't call Vue instance inside the autosave function.
https://i.stack.imgur.com/5Nyq4.jpg
https://i.stack.imgur.com/sevjo.jpg
I can't call my vue instance by 'this',that means i can't use methods,vuex store...and so on.
How can i fix hti?

I know this is a bit late but for anyone (like myself) looking for an answer to this I followed the advice in this [SO link][1]
data() {
var self = this
...
return {
editorConfig: {
autosave: {
waitingTime: 3000, // in ms
save(editor) {
self.saveData(editor.getData())
}
},
}
}
}
[1]: https://stackoverflow.com/a/61509032/558720

Related

fire event from external controller

i'm moving to Rails 7 and i feel like there are so many changes but i'm confident on understanding them and be able to upgrade a personal applications i made myself for keeping my personal records and appointments
More specific i need to communicate between controllers (#hotwire/stimulus) between a flatpickr controller and fullcalendar contorller. The idea is to jump to a date when selecting from flatpicr
I've tried so many diferent options but i'm really stuck.. any help is welcome :)
Rails 7.0.3.1
index.html.erb
<div data-controller="flatpickr" name="" data-action=""></div>
<div data-controller="calendar">
<div data-calendar-target="window"></div>
<turbo-frame id="popup" data-calendar-target="popup"></turbo-frame>
</div>
flatpickr_controller.js
import Flatpickr from 'stimulus-flatpickr'
export default class extends Flatpickr {
connect() {
this.config = {
inline: true,
enableTime: false,
time_24hr: false,
onChange: function(selectedDates, dateStr, instance) {
const calendarController = this.application.getControllerForElementAndIdentifier(this.calendarTarget, "calendar")
calendarController.gotoDate('18-01-2025') //random date
},
};
super.connect();
}
}
calendar_controller.js
import { Controller } from "#hotwired/stimulus";
import { Calendar } from '#fullcalendar/core';
import resourceTimeGridPlugin from '#fullcalendar/resource-timegrid';
import interactionPlugin from '#fullcalendar/interaction';
export default class extends Controller {
static targets = [ "popup", "window" ];
connect() {
let overlay = this.popupTarget;
this.calendar = new Calendar(this.windowTarget, {
plugins: [ resourceTimeGridPlugin, interactionPlugin ],
themeSystem: 'bootstrap5',
initialView: 'resourceTimeGridDay',
aspectRatio: 1.8,
nowIndicator: true,
selectable: true,
editable: true,
allDaySlot: false,
});
window.addEventListener('load', () => {
this.calendar.render();
});
}
refresh(e) {
if (e.detail.success) {
this.calendar.refetchEvents();
}
}
}
output
application-7082a89999639e6d01ae0ef0aaaf6707b39fab96541f1dcd1c79da24753cb0ed.js:28271 Uncaught TypeError: Cannot read properties of undefined (reading 'getControllerForElementAndIdentifier')
at Object.onChange (ap ...
I think I'm gonna get mad with this... thank you!
Well done on trying to understand all of this, it can be hard to learn something new and especially when you have 'working' code and you are kind of forced to change.
One thing that can help is to revisit the Stimulus documentation, it does have pretty much all the answers you need for these issues but maybe needs a bit of a re-read.
The other thing which can be super frustrating is JavaScript's usage of this and how it works.
Hopefully the below breakdown helps.
Problems
1. Understanding this (JavaScript)
The first problem with the code above is that you are referencing this with the assumption that it refers to your controller instance, but rather it is referring to the event's context.
onChange: function(selectedDates, dateStr, instance) {
const calendarController = this.application.getControllerForElementAndIdentifier(this.calendarTarget, "calendar")
calendarController.gotoDate('18-01-2025') //random date
},
In the above code, this.application and this.calendarTarget will never work as the this here is the context created by the onChange handler calling context.
The quick way around this this issue is to just use an arrow function. In the below revised code snippet (which will still not work, due to issues 2 & 3 below), the arrow function approach is used instead of a function declaration, which pulls in the this from the parent context, which will be the Controller's instance.
onChange: (selectedDates, dateStr, instance) => {
const calendarController = this.application.getControllerForElementAndIdentifier(this.calendarTarget, "calendar")
calendarController.gotoDate('18-01-2025') //random date
},
The best way, however, is to read the documentation on Mozilla here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this in full, read it again and then maybe a third time. After that, find some YouTube videos and watch those. You will find JavaScript development much easier if you truly 'grok' this concept, but it is hard to understand.
2. Understanding Stimulus Targets
The next issue is your use of this.calendarTarget in your flatpackr controller, this controller will not have any target available due to it not being set up correctly.
In the Stimulus docs - https://stimulus.hotwired.dev/reference/targets you can read that the target must be in the controller's scope. But in the HTML below the data-controller="flatpickr" div has no children and also has no targets in the HTML anywhere that can be accessed by this controller.
<div data-controller="flatpickr" name="" data-action="">No Children here?</div>
<div data-controller="calendar">
<div data-calendar-target="window"></div>
<turbo-frame id="popup" data-calendar-target="popup"></turbo-frame>
</div>
There are a few ways to access something outside the controller's scope, but the easiest way would be to bypass this problem all together and use the Stimulus' preferred way to communicate with other controllers.
But, if you want to use a target you need to do two things.
A. Ensure the target static attribute is declared on your controller.
export default class extends Flatpickr {
static targets = [ "calendar" ]; // this is required
B. Ensure the target element has the right attribute and is a child of the desired controller.
<div data-controller="flatpickr" name="" data-action="">
<div data-controller="calendar" data-flatpickr-target="calendar">
<div data-calendar-target="window"></div>
<turbo-frame id="popup" data-calendar-target="popup"></turbo-frame>
</div>
</div>
3. Stimulus Cross-Controller Coordination With Events
Finally, your use of getControllerForElementAndIdentifier is documented as a work around if there is no other way to communicate with another controller.
The preferred way is using events and it is incredibly powerful, flexible and will probably solve 99.9% of your use cases. Have a read of https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent & https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent if you are not sure what browser events are first.
Then, you can dispatch an event from your flatpackr controller for your calendar controller to pick up on.
The simplest way to go about this is an event that jut gets dispatched on your first controller and 'bubbles' up the DOM and then your calendar controller listens to this globally.
Solution - Example Code
First, start with your HTML, the only real change below is the data-action attribute on your calendar.
This will listen for a global event flatpackr:changed and when it sees that, it will call your calendar controller's method goToDate.
<div data-controller="flatpickr"></div>
<div data-controller="calendar" data-action="flatpackr:changed#window->calendar#goToDate">
<div data-calendar-target="window"></div>
<turbo-frame id="popup" data-calendar-target="popup"></turbo-frame>
</div>
In your flatpackr controller, using the arrow function approach described above, you can call this.dispatch() which will trigger the dispatching of a CustomEvent with the supplied options.
Stimulus will prefix the name supplied with the controller's name.
Note: You could be more specific with where this event gets dispatched to, but if there is only ever going to be one calendar instance, no need to worry for now.
import Flatpickr from 'stimulus-flatpickr'
export default class extends Flatpickr {
connect() {
this.config = {
inline: true,
enableTime: false,
time_24hr: false,
onChange: (selectedDates, dateStr, instance) => {
// note: Stimulus sets `bubbles` to true by default but good to be explicit
const someDate = '18-01-2025'; // random date
// passing data to the other controller can be via the `detail` object in the CustomEvent & Stimulus will automatically add 'flatpackr:' to the start of the event name for you (Thanks Stimulus!)
this.dispatch('changed', { detail: { date: someDate } , bubbles: true } );
},
};
// super.connect(); - not sure that you need this in most cases so commented out
}
}
In the calendar controller, all that is needed is the method to be declared goToDate.
You can read the supplied detail in the event.detail from the param.
import { Controller } from "#hotwired/stimulus";
import { Calendar } from '#fullcalendar/core';
import resourceTimeGridPlugin from '#fullcalendar/resource-timegrid';
import interactionPlugin from '#fullcalendar/interaction';
export default class extends Controller {
static targets = [ "popup", "window" ];
connect() {
// ...
// note: you may not need the window on load listener as `connect` will only be called when there is a DOM ready to attach to.
}
refresh(e) {
// ...
}
goToDate(event) {
// note: you can use destructuring above and change the signature to ` goToDate({ detail: { date } }) {` instead
const date = event.detail.date;
console.log('do something with the date now', date);
}
}
Note: I have not tested locally but should be close enough

Use i18n with data fetched from Wordpress RestAPI

I'm stuck since a while on this problem now and I'm struggling to find answers or peoples that have experienced the same problem.
Also, I'm not a native English speaker and I'm new to programming, so sorry if it's not clear / if my approch is dumb as f
I decided to turn the Wordpress of my company to headless (on Nuxt). Everything was pretty fine until I tried to internationalized the app. The best solution (I think) to manage this task is to use nuxt-i18n, a tool to properly translate the app (strings, paths etc). But this solution seems to not be very compatible with data fetched from the Rest API.
For now I'm trying to passing the data from single page like that :
<script>
import SwitchL from '~/components/LanguageInput.vue'
export default {
components: {
SwitchL,
},
data() {
return {
fetchRestFr: null,
fetchRestEn: null,
i18nData: null,
}
},
i18n: {
messages: {
// help
}
},
methods: {
fetchSomeData() {
// Get page data in French
let fetchRestFr = this.$axios.$get(`https://www.company-site.com/wp-json/wp/v2/pages?include=42&lang=fr`);
// Get page data in English
let fetchRestEn = this.$axios.$get(`https://www.company-site.com/wp-json/wp/v2/pages?include=42&lang=en`);
// Assign data to null variables
this.fetchRestFr = fetchRestFr[0]
this.fetchRestEn = fetchRestEn[0]
// Build the i18n object
this.dataToI18n();
},
dataToI18n() {
if (this.fetchRestFr && this.fetchRestEn) {
let fr = this.fetchRestFr
let en = this.fetchRestEn
let data = {
messages: {
fr,
en
}
}
this.i18nData = data
}
},
},
created() {
this.fetchSomeData();
},
}
</script>
An other approch was to use the tag outside the template section like so :
<i18n>
// Inject the data generated from a function
{
"en": {
"data": "here"
},
"fr": {
"data": "ici"
}
}
</i18n>
But I don't find any solution to dynamically inject JSON here.
Last solution is to make things to preper way, by creating JSON file for i18n to referencing, but I think It will be pretty hard for me to do this, and to manage this on long term.
If you have advice, thoughts on this I will be very grateful !
You do usually use some JSON files directly. They will be stored into /locales/fr.json with something like this
{
"here": "ici"
}
Then, you'll access it into your template with
<template>
<p>{{ $t('here') }}</p>
</template>
And it will handle the fr/en switch by the several ways available (manual switch, checking browser's locale, URL's path, cookie etc).
You can check nuxt-i18n's documentation for this and get a proper simple setup quickly here: https://i18n.nuxtjs.org/
Usually, you won't need to use the i18n tag anymore but if you still need to, you can do as explained here: https://i18n.nuxtjs.org/per-component-translations

Is it possible to call own Method in Vue data()?

So I'm using Element Vue, I need to get access to a method or to the value of the
acceptedDates
export default {
data() {
return {
acceptedDates: [],
pickerOptions1: {
disabledDate(time) {
return moment(time).isBetween(this.acceptedDates[0], this.acceptedDates[1]);
}
}
};
},
methods: {
//setting acceptedDates method...
}
I get a ReferenceError for this.accptedDates or even without using this. How do you do this?
Update
Thank you for the first anwsers, but I still can't figure it out.
I created this fiddle for you to see: https://jsfiddle.net/05nru5xq/13/
If you go to http://element.eleme.io/#/en-US/component/date-picker you will find that disabledDate is a Function in PickerOption.
Now that I know exactly what you are after, I've updated accordingly to your example https://jsfiddle.net/05nru5xq/31/
some points on your code:
never use capital to name methods, capital letter first is to name Object that can be created with the new attribute;
today is not a moment object so you can't call isBetween on it
from the docs you need to name your options as there's 3 of them, hence specifying the option :picker-options="{ disabledDate: betweenOneWeek }"
data is just a place to hold variables, don't put methods there.
As a side note:
I've done the same (bought it for me) and I'm not in any way affiliated with them, just a happy customer. If you want to know VueJs well enough and quick, try this Udemy course, it's pretty good and worth all the money
In the data section you can define variables with functions but you're not able to do things like you did. Why? It's simple. You're using this which binding to pickerOptions1 object, not data. Even when you use arrow function in object it won't work as well because in that case it will return window object.
Those operations on data you can move to separate function and in my opinion it would be the best way.
For example you can do something like that:
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!',
customMessage: 'Test ',
testFunction() {
this.customMessage += this.message;
alert(this.customMessage);
}
},
mounted() {
this.testFunction();
}
})
https://jsfiddle.net/mxuh7c9p/
or more suitable to your case:
new Vue({
el: '#app',
data: {
acceptedDates: [],
pickerOptions1: null,
},
methods: {
getDisabledDate(time) {
return moment(time).isBetween(this.acceptedDates[0], this.acceptedDates[1]);
},
setAcceptedDates() {
const disabledDate = this.getDisabledDate(time);
// do something
}
},
mounted() {
//this.getDisabledDate();
}
})
https://jsfiddle.net/mxuh7c9p/13/

adding jquery validation to kendo ui elements

I've looked at many posts on this and have it working to the extent that it does validate my fields when I add the following.
$.validator.setDefaults({
ignore: []
});
The part I'm still missing is adding the input-validation-error class to notify the user. It is working fine for my other input elements (non-kendo). I've tried adding the class manually in $.validator.setDefaults as well but nothing seems to be working.
Is there an example out there somewhere or has anyone gotten it to work?
I'm not certain I'm doing this right but here's what I've tried to add it manually.
$.validator.setDefaults({
ignore: [],
errorClass: "input-validation-error",
errorElement: "input",
highlight: function (element, errorClass) {
$(element).addClass(errorClass)
},
unhighlight: function (element, errorClass) {
$(element).removeClass(errorClass)
}
});
I found a solution to this based on this post. Basically what you need to do is look for the parent element that the input is wrapped in. Something like this:
$.validator.setDefaults({
ignore: [],
highlight: function (element, errorClass) {
element = $(element);
if (element.parent().hasClass("k-widget")) {
element.parent().addClass('input-validation-error');
} else {
element.addClass('input-validation-error')
}
},
unhighlight: function (element, errorClass) {
element = $(element);
if (element.parent().hasClass("k-widget")) {
element.parent().removeClass('input-validation-error');
} else {
element.removeClass('input-validation-error')
}
}
});
I would advise anyone though to visit the post I've linked to above before taking off down this particular rabbit hole as it introduces another issue, just to be aware of what you're getting into. The excepted answer is really more relevant to this question than the one being asked there.

My Ember's controller's properties are being literally echoed

I've been during a while working with Ember.js. Now I'm getting a weird behaviour that I cannot fix. Is not the first time I experience it, but in previous occasions I figured it out after making little changes. But now, I really have no idea what's causing the conflict. The issue is occuring in Controllers. I have this ridiculously simple controller, just for testing:
App.AppColleaguesController = Ember.ArrayController.extend
(
{
needs: ['app'],
aNumber: function()
{
return this.get('controllers.app.personId');
}
}
);
Of course, that property is defined on the AppController:
App.AppController = Ember.ArrayController.extend
(
{
loggedIn: false,
personId: -1,
personName: '',
location: '',
logOut: function()
{
if (window.confirm("Do you want log out?"))
{
this.set('loggedIn', false);
this.set('personId', -1);
this.set('personName', '');
this.set('location', '');
this.send('goToLogin');
}
}
}
);
In my template, I'm getting this result:
... This is a number: function () { return
this.get('controllers.app.personId'); } ...
My template is as straightforward as this:
...
This is a number: *{{aNumber}}*
{{debug}}
{{log aNumber}}
...
The debugging statements in my template are showing me this in Firebug console:
...
Transitioned into 'app.colleagues'
function()
...
So, is like the function is literally echoed, not "interpreted". In fact I'm getting this sort of problem in a couple more of controllers, but the rest of them (they are a lot, like 8 or 10 controllers) are working nice. Do you have any idea about the problem? Is my mistake, or maybe an Ember issue?
Thanks a lot in advance! I hope you can help me.
You forgot the .property after the function. This is needed by Ember to indicate that a function is a computed property.
aNumber: function() {
return this.get('controllers.app.personId');
}.property('app.personId')