I want to integrate ckeditor in the app. Any pointers or steps in that direction will really help.
Below steps I followed.
npm install --save #ckeditor/ckeditor5-build-classic
path_mapping.json entry
"ckeditor": {
"cdn": "3rdparty",
"cwd": "node_modules/#ckeditor/ckeditor5-build-classic/build",
"debug": {
"src": ["ckeditor.js", "ckeditor.js.map"],
"path": "libs/ckeditor/ckeditor.js",
"cdnPath": "ckeditor/ckeditor"
},
"release": {
"src": ["ckeditor.js", "ckeditor.js.map"],
"path": "libs/ckeditor/ckeditor.js",
"cdnPath": "ckeditor/ckeditor"
}
}
web/js/libs/ckeditor folder is created.
main.js entry
'ckeditor': 'libs/ckeditor/ckeditor'
defined 'ckeditor' in viewModel also but still getting error:-
in view
<textarea id="feedback" data-bind="jqueryUI:{component: 'ckeditor', value: value, skin: 'moono-lisa', toolbar: 'basic', uiColor : '#9AB8F3'}"/>
Component ckeditor is not found
The following worked for me. What I tried is exactly as per ckeditor documentation.
Scaffold a vanilla jet application using ojet create ckEditor
npm install --save #ckeditor/ckeditor5-build-classic
Do the path-mappings.json changes to include ckeditor into the app.
"ckeditor": {
"cdn": "3rdparty",
"cwd": "node_modules/#ckeditor/ckeditor5-build-classic/build",
"debug": {
"src": ["ckeditor.js", "ckeditor.js.map"],
"path": "libs/ckeditor/ckeditor.js",
"cdnPath": "ckeditor/ckeditor"
},
"release": {
"src": ["ckeditor.js", "ckeditor.js.map"],
"path": "libs/ckeditor/ckeditor.js",
"cdnPath": "ckeditor/ckeditor"
}
}
Modify index.html to add this into the body tag:
<div id="globalBody">
<h1>CK Editor on Oracle JET</h1>
<div id="editor">
<p>This is the editor content.</p>
</div>
</div>
Create an appController.js (optional, you can add the ckeditor require directly on to main.js, but I prefer this)
define(['knockout', 'ckeditor'], function(ko, ClassicEditor) {
var Controller = function() {
// This code is taken directly from the readme of ckeditor
// https://github.com/ckeditor/ckeditor5-build-classic
ClassicEditor.create(document.querySelector( '#editor' ))
.then(editor => {
window.editor = editor;
})
.catch(err => {
console.error( err.stack );
});
};
return new Controller();
});
Add appController to main.js and bind it:
require(['ojs/ojcore', 'knockout', 'jquery', 'appController', 'ojs/ojknockout'],
function (oj, ko, $, app) {
$(function () {
function init() {
ko.applyBindings(app, document.getElementById('globalBody'));
}
// If running in a hybrid (e.g. Cordova) environment, we need to wait for the deviceready
// event before executing any code that might interact with Cordova APIs or plugins.
if ($(document.body).hasClass('oj-hybrid')) {
document.addEventListener('deviceready', init);
} else {
init();
}
});
}
);
Run the app. You can see the CKEditor working.
Related
I am trying to integrate Stripe Checkout into my Laravel Vue.js application. I watched a tutorial on YouTube. However, I get the following error.
Vue Stripe will not work on an insecure host. Make sure that your site
is using TCP/SSL.
<template>
<div class="py-8 flex justify-center">
<stripe-checkout
ref="checkoutRef"
mode="payment"
:pk="publishableKey"
:sessionId="sessionId"
/>
<button class=" bg-blue-500 px-2 py-1 rounded text-white" #click="submit">Pay now!</button>
</div>
</template>
<script>
import { StripeCheckout } from "#vue-stripe/vue-stripe";
import axios from "axios";
export default {
components: {
StripeCheckout ,
},
data() {
return {
publishableKey: "pk_test_51KtYynFJTg08EEU2sYHLN0LKrnZTuJCazai8jmokQ2096V7IXYjX2XsdGi7xh5jOgSCz5nnn7YfJS5afTtEHRSxk00EUEcmhsj",
sessionId: null,
};
},
mounted() {
console.log("Component mounted.");
this.getSession()
},
methods: {
getSession() {
axios.get('getSession').then(res => {
this.sessionId = res.data.id
}).catch(err => {
});
},
submit () {
this.$refs.checkoutRef.redirectToCheckout();
}
}
};
</script>```
According to the docs you can register it as a plugin where you can define a testMode option to override the insecure host warning
import Vue from 'vue';
import { StripePlugin } from '#vue-stripe/vue-stripe';
const options = {
pk: process.env.STRIPE_PUBLISHABLE_KEY,
testMode: true, // Boolean. To override the insecure host warning
stripeAccount: process.env.STRIPE_ACCOUNT,
apiVersion: process.env.API_VERSION,
locale: process.env.LOCALE,
};
Vue.use(StripePlugin, options);
I have a computed property that is not working correctly. When reading the docs this is how it should be done for Vue 2.x. The code i have:
<template>
<div>
<button :disabled="isDisabled">Import configurator data</button>
<input class="input" type="file" id="file" v-on:change="setFile">
</div>
</template>
<script lang="js">
export default {
data: () => {
return {
importDisabled: true,
}
},
computed: {
isDisabled() {
return this.importDisabled;
},
},
methods: {
setFile: (e) => {
this.importDisabled = false;
},
}
}
</script>
Expected behaviour: Button enables when a file is selected.
Actual behaviour: Button stays disabled.
What am i missing here? A console.log within the isDisabled() methods shows it is only called once. It is not called after importDisabled changes.
Other info:
vue 2.6.12
laravel nova
Also note: Vue tools does not detect a Vue component in the inspector. But the Vue behaviour is working when loading the tool.
It seems arrow functions are bound to the parent context. That was the reason my code did not work. this is then not bound to the Vue instance but the parent (Window) which causes it not to work.
Wrong:
setFile: (e) => {
this.importDisabled = false;
},
Right:
setFile: function() {
this.importDisabled = false;
},
More information:
https://codingexplained.com/coding/front-end/vue-js/using-es6-arrow-functions-vue-js
I'm trying to add dynamically an image to the FullCalendar events with Vue. But first of all, I'm testing with a static data and the image doesn't show up.
This is what I'm trying to do after several research:
<template>
...
<FullCalendar
defaultView="timeGridWeek"
header="null"
:slotDuration="slotDuration"
:plugins="calendarPlugins"
#dateClick="handleDateClick"
:allDaySlot="false"
:columnHeaderFormat='columnHeaderFormat'
:hiddenDays="hiddenDays"
:themeSystem="themeSystem"
:minTime="minTime"
:maxTime="maxTime"
:contentHeight="contentHeight"
:events="tutor_applications_not_scheduled"
:config="config"
#eventRender="eventRender"
/>
...
</template>
<script>
import moment from 'moment'
import FullCalendar from '#fullcalendar/vue'
import dayGridPlugin from '#fullcalendar/daygrid'
import timeGridPlugin from '#fullcalendar/timegrid'
import interactionPlugin from '#fullcalendar/interaction'
import bootstrapPlugin from '#fullcalendar/bootstrap'
export default {
components: {
FullCalendar
},
data(){
return {
tutor_application_setup_id: this.$route.params.tutor_application_setup_id,
loading: false,
uri: '/tutor-applications-schedules/',
calendarPlugins: [dayGridPlugin, timeGridPlugin, interactionPlugin, bootstrapPlugin],
slotDuration: '01:00',
columnHeaderFormat: {weekday:'long'},
hiddenDays: [], //[0,6] - Sunday and Saturday
themeSystem: 'bootstrap',
minTime: '10:00', // will be dynamic
maxTime: '17:00', // will be dynamic
contentHeight: 'auto',
config: {
timeFormat: 'h(:mm) a',
eventClick: function(event) {
if (event.url) {
location.replace(event.url);
return false;
}
}
},
tutor_applications_schedules: [],
tutor_applications_not_scheduled: [],
tutor_applications_scheduled: [],
errors: [],
}
},
methods: {
handleDateClick(arg){
alert(arg.date)
},
loadTutorApplicationsSchedules(){
axios.get(this.uri + this.tutor_application_setup_id).then(response=>{
this.tutor_applications_schedules = response.data.tutor_applications_schedules
this.loadTutorApplicationsNotScheduled()
this.loading = true
});
},
loadTutorApplicationsNotScheduled(){
// this.tutor_applications_schedules.forEach(schedule => {
// if(!schedule.is_scheduled){
this.tutor_applications_not_scheduled.push({
title: 'TEST TITLE',
start: '2019-05-22 10:00',
end: '2019-05-22 13:00',
imageurl: '/images/profile/1557196883.png'
});
// }
// });
},
eventRender: function(event, eventElement) {
console.log(event) // returning everything
console.log(event.imageurl) // returning undefined
if (event.imageurl) {
eventElement.find("div.fc-content").prepend("<img src='" + event.imageurl +"' width='16' height='16'>");
}
},
loadTutorApplicationsScheduled(){
},
moment: function (date) {
return moment(date)
},
},
mounted(){
this.loadTutorApplicationsSchedules()
}
}
</script>
The result returns only the time and the title in the correct date.
I also tried to insert the img tag to the title attribute, and changed the eventRender, like below:
...
title: '<img src="/images/profile/1557196883.png" />TEST TITLE',
...
eventRender: function(event, element, view) {
var title = element.find( '.fc-title' );
title.html(title.text());
},
It's returning the html tag as string, like <img src="/images/profile/1557196883.png" />TEST TITLE.
Some of my dependencies are:
"vue": "^2.5.17",
"#fullcalendar/bootstrap": "^4.1.0",
"#fullcalendar/core": "^4.1.0",
"#fullcalendar/daygrid": "^4.1.0",
"#fullcalendar/interaction": "^4.1.0",
"#fullcalendar/timegrid": "^4.1.0",
"#fullcalendar/vue": "^4.1.1",
"babel-runtime": "^6.26.0",
"vue-full-calendar": "^2.7.0",
I don't know which approach to follow anymore. Any help? Thank you.
UPDATE
I realized that some params has changed (Full Calendar Updates) and I changed my eventRender function, and now I can read the imageurl. However, I'm stuck how in Vue to find a tag and prepend with my image tag.
My code now is like this:
eventRender: function(info) {
console.log(info) // returning everything
console.log(info.event.extendedProps.imageurl) // returning the image path correctly
if (info.event.extendedProps.imageurl) {
info.el.find("div.fc-content").prepend("<img src='" + info.event.extendedProps.imageurl +"' width='16' height='16'>"); // this line is the problem now
}
},
It's returning the error [Vue warn]: Error in v-on handler: "TypeError: info.el.find is not a function", and I don't know how to fix it.
For whom it may concern :), this thread helped me, and I figured out what to do. I changed my eventRender to this:
eventRender: function(info) {
if (info.event.extendedProps.imageurl) {
info.el.firstChild.innerHTML = info.el.firstChild.innerHTML + "<img src='" + info.event.extendedProps.imageurl +"' width='40' height='40'>";
}
},
In this case, I can be even more flexible like:
info.el.firstChild.innerHTML = "<div><h4><a href='#'>"+ info.event.title +"</a></h4><img src='" + info.event.extendedProps.imageurl +"' width='40' height='40'></div>";
etc.
I hope this can help someone else!
Define a variable in data as imageURL: "",
Define img tag in html where you want to show it as
<img v-if="imageURL!=''" :src="imageURL" width='16' height='16'>
Your renderer function
eventRender: function(info) {
if (info.event.extendedProps.imageurl) {
this.imageURL = info.event.extendedProps.imageurl;
}
}
This is how I did mind by putting this function into methods
eventRender(info) {
info.el.firstChild.innerHTML = `
<a class="rounded-lg fc-day-grid-event fc-h-event fc-event f-start fc-end">
<div class="h-12">
<span class="fc-title text-white flex ml-3">
<img class="img-circle avatar-small h-8 w-8 p-1" src="${info.event.extendedProps.imageurl}">
<span class="ml-3 self-center font bold">${info.event.extendedProps.username}</span>
</span>
</div>
</a>
`
},
Now to change color dynamically for each event I did it from Laravel Resource
'backgroundColor' => $this->status === 1 ? '#48BB78' : '#F6E05E'
Tried to use :class inside the eventRender and didn't work.
So you can just send in the API the color you want based on a condition instead and perform the operation on laravel.
i have problem with showing vue variable on blade template
my layouts/master.blade.php
<html>
<head>
<title>#yield('title') | My company</title>
.....
news.blade.php
#extends('layouts.master')
<div id="pagetitle">
#section('title', #{{pagetitle}} )
</div>
#section('content')
....
#endsection
resources/js/news.js
new Vue({
el: '#pagetitle',
data: {
pagetitle:'',
},
mounted() {
this.fetchArticlesPage();
},
methods: {
fetchArticlesPage(page_url) {
page_url = '/api/articles/news';
fetch(page_url)
.then(res => res.json())
.then(res => this.pagetitle = res.page_title)
.catch(err => console.log(err));
},
}
});
and this response data from controller with jsonResource
{
"links": {
"first": "http://localhost:8000/api/articles/news?page=1",
"last": "http://localhost:8000/api/articles/news?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "http://localhost:8000/api/articles/news",
"per_page": 3,
"to": 3,
"total": 3
},
"page_title": "News"
}
i got syntax error unexpected {
if i put on #section('content') like this
#section('content')
<div id="pagetitle">
#{{pagetitle}}
</div>
#stop
it' fine and will show the data which is "News",
please help, am new in vue and laravel programing
The Blade template directives are processed in the server and a response sent to the client.
After this, Vue template directives are processed in the browser.
On that account, the later example with the escaped Vue mustache works as expected as the block below is sent to the browser as a part of the overall response content.
<div id="pagetitle">
{{pagetitle}}
</div>
The Vue program running in the browser then runs, and interpolates variables in this template.
For the former example,
#section('title', #{{pagetitle}})
will result in an error in the server when it tries to compile the section as the second parameter is not given as a string.
This error can be corrected by quoting the escaped Vue mustache.
#section('title', '#{{pagetitle}}')
EDIT: {{pagetitle}} is not compiled is in document head
The Vue instance that is created is mounted on an element contained in the body. For this reason, compilation happens only on the document tree of the element that the Vue instance is mounted on.
I suggest to create a separate Vue instance to manage the head of the document. e.g.
const helmet = new Vue({
el: 'head',
data: {
pagetitle:'',
},
mounted() {
this.fetchArticlesPage();
},
methods: {
fetchArticlesPage(page_url) {
page_url = '/api/articles/news';
fetch(page_url)
.then(res => res.json())
.then(res => this.pagetitle = res.page_title)
.catch(err => console.log(err));
},
}
})
u can try this
#section('title', #pagetitle)
Using Laravel 5.3, I have the following in /resources/assets/js/app.js:
require('./bootstrap');
require('./components/test-component'); // custom
const app = new Vue({
el: '#app'
});
The component test-component.js is simply
Vue.component('test-component', {
data() {
return {
someData: '' // does work!
};
},
mounted() {
console.log('ready'); // does not fire...
},
methods: {
testMethod() {
console.log('here'); // does not fire...
}
}
});
Then in a Blade template,
<test-component>
<form>
<!-- a bunch of HTML markup here... -->
<button type="button" #click="testMethod">Fire a test method...</button>
</form>
</test-component>
When a button is clicked, nothing shows in the console. Moreover, mounted does not fire when the form is loaded. At the same time, someData model binding works perfectly!
Question
What I am doing wrong here?
You need to add template to component options:
Vue.component('test-component', {
template: ` <form>
<!-- a bunch of HTML markup here... -->
<button type="button" #click="testMethod">Fire a test method...</button>
</form>`,
//..
});
You should add a template:
Vue.component('test-component', {
data() {
return {
someData: '' // does work!
};
},
template: '<div></div>', // add your template here
mounted() {
console.log('ready'); // does not fire...
},
methods: {
testMethod() {
console.log('here'); // does not fire...
}
}
});