I'm building a sort of article editor, for this I'm using the Angular Integration for CKEditor5; following the documentation I can correctly use the ClassicEditor build with the ckeditor component.
These are my files:
import { Component, OnInit } from '#angular/core';
import * as ClassicEditor from '#ckeditor/ckeditor5-build-classic';
#Component({
selector: 'app-edit-article',
templateUrl: './edit-article.component.html',
styleUrls: ['./edit-article.component.scss']
})
export class EditArticleComponent implements OnInit {
constructor() { }
public Editor = ClassicEditor;
articleForm: FormGroup;
ngOnInit() {
}
}
Template
<div class="row">
<div class="col-12">
<label for="">Content</label>
<ckeditor [editor]="Editor" id="editor" class="blue-scroll--light" formControlName="content"></ckeditor>
</div>
</div>
Unfortunately, the ClassicEditor build referenced in that guide does not include many plugins, so I'm trying to add some of them, like text alignment, font color, font size, etc.
It seems that I need to create a custom build which includes all of the desired features and then reference that build instead of the ClassicEditor in my typescript file if I understand correctly, so I went ahead and used their online builder to create a build with all the plugins already included, but after that I'm not sure how to proceed and the documentation isn't really clear.
As far as I understand, I need to add the build folder inside my Angular App and then import the ckeditor.js file in my component, like this:
import * as Editor from '../../../../../core/libs/ckeditor5/build/ckeditor';
and change the declaration of the Editor to use that import instead of the ClassicEditor, so:
public Editor = Editor;
However as soon as I make that change I'm no longer able to even run the app, since I get the following error:
ERROR Error: Uncaught (in promise): CKEditorError: ckeditor-duplicated-modules: Some CKEditor 5 modules are duplicated. Read more: https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/error-codes.html#error-ckeditor-duplicated-modules
CKEditorError: ckeditor-duplicated-modules: Some CKEditor 5 modules are duplicated. Read more: https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/error-codes.html#error-ckeditor-duplicated-modules
at Object.<anonymous> (ckeditor.js:5)
at Object.push../src/app/core/libs/ckeditor5/build/ckeditor.js (ckeditor.js:5)
at i (ckeditor.js:5)
at Module.<anonymous> (ckeditor.js:5)
at i (ckeditor.js:5)
at push../src/app/core/libs/ckeditor5/build/ckeditor.js (ckeditor.js:5)
at ckeditor.js:5
at ckeditor.js:5
at Object../src/app/core/libs/ckeditor5/build/ckeditor.js (ckeditor.js:5)
at __webpack_require__ (bootstrap:84)
at resolvePromise (zone.js:852)
at resolvePromise (zone.js:809)
at zone.js:913
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Object.onInvokeTask (core.js:30885)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
at drainMicroTaskQueue (zone.js:601)
Again, the docs say it is due to multiple imports being made but I don't understand how since I'm only using the ckeditor.js file that comes in the build I just generated, which works fine if referenced in a plain HTML file.
Can someone provide an example on how to successfully make a Custom Build work in a Angular App?
After a while, I found that the problem seems to be that I had another build imported in a different module of my application.
So I was only using the custom build inside my EditArticle component by importing and using that file, but I also had other components on other modules that were importing and using the ClassicEditor build that I installed through NPM, which looks like it was causing the error.
The fix was not to remove the ClassicEditor package nor removing the import ClassicEditor statement, but just making sure that that specific import was not being used anywhere else in the app, since I guess during compilation Angular removes all unused imports.
Once I did this, the application ran fine with my custom build.
Just to clear it up, I can have these two imports on the same file or multiple components
import * as ClassicEditor from '#ckeditor/ckeditor5-build-classic';
import * as Editor from 'src/app/core/libs/ckeditor5/build/ckeditor';
But I should only be using one of them on the entire app, so if I have an Editor on Component1 and on Component2, I can have both builds imported, but on the declaration of the Editor property I should only use one, and it should be the same one on every component the app uses, so:
This works
Component1
import * as ClassicEditor from '#ckeditor/ckeditor5-build-classic';
import * as Editor from 'src/app/core/libs/ckeditor5/build/ckeditor';
public Editor = Editor;
Component2
import * as ClassicEditor from '#ckeditor/ckeditor5-build-classic';
import * as Editor from 'src/app/core/libs/ckeditor5/build/ckeditor';
public Editor = Editor;
This WON'T work
Component1
import * as ClassicEditor from '#ckeditor/ckeditor5-build-classic';
import * as Editor from 'src/app/core/libs/ckeditor5/build/ckeditor';
public Editor = Editor;
Component2
import * as ClassicEditor from '#ckeditor/ckeditor5-build-classic';
import * as Editor from 'src/app/core/libs/ckeditor5/build/ckeditor';
public Editor = ClassicEditor;
You can of course just remove the unused build from the imports altogether and that'll work too. Just again, make sure you use the same build on all the application
console.log(this.ckEditorClassic.builtinPlugins.map( plugin => plugin.pluginName ));
}
This will give you the list of plugins in the custom build.
My sample has :
["Alignment", "AutoImage", "Autoformat", "Autosave", "BlockQuote", "Bold", "CodeBlock", "Essentials", "ExportPdf", "ExportWord", "FontBackgroundColor", "FontColor", "FontFamily", "FontSize", "Heading", "Highlight", "HorizontalLine", "Image", "ImageCaption", "ImageInsert", "ImageResize", "ImageStyle", "ImageToolbar", "ImageUpload", "Indent", "IndentBlock", "Italic", "Link", "List", "Markdown", "MathType", "MediaEmbed", "MediaEmbedToolbar", "PageBreak", "Paragraph", "PasteFromOffice", "SpecialCharacters", undefined, undefined, undefined, undefined, undefined, "Strikethrough", "Subscript", "Superscript", "Table", "TextTransformation", "WordCount"]
take the displayed list within [] and replace xxxx with it.
<ckeditor [config]="{toolbar:[xxxx] }"
Related
playing around with Rails 7 and import maps. Trying to import a folder with some custom JS.
# config/importmap.rb
pin_all_from "app/javascript/custom", under: "custom"
# app/javascript/application.js
import "custom"
Gives Uncaught TypeError: Failed to resolve module specifier "custom" on Chrome
and Uncaught Error: Unable to resolve specifier 'custom' from [shim] on Firefox
interestingly import "custom/script" works fine.
what am I doing wrong?
I had this same problem and found the following solution:
# app/javascript/application.js
import "custom/my_custom_code.js"
This means that
pin_all_from "app/javascript/custom", under: "custom" is really just making each custom JS file available under the custom namespace. Therefore, you still need to import each file individually.
While this might still be a valid thing to do in some use cases, I think what I was trying to do was a bit of an anti-pattern in Rails 7.
It is very easy to use Stimulus controllers instead.
Stimulus Handbook For reference
For example, to dismiss an alert when a user clicks the "x"
// app/javascript/alerts_controller.js
import { Controller } from "#hotwired/stimulus"
export default class extends Controller {
dismiss () {
this.element.style.display = 'none';
}
}
<div data-controller="alerts">
<h2> Alert! </h2>
<span data-action="click->alerts#dismiss"><i class="fas fa-times"></i></span>
</div>
I'm trying to create a wrapper as a React component for this DateTimePicker jQuery plugin. So far it's working, but I'm trying to set it's locale and to do that I need to import a specific file from the library.
I'm doing so at require('gijgo/js/messages/messages.pt-br'), however it throws an error ReferenceError: gj is not defined. The object gj is imported at require('gijgo/js/gijgo'); and I already tried doing something like this:
const gj = require('gijgo/js/gijgo');
window.gj = gj;
require('gijgo/js/messages/messages.pt-br')
Just like I did to import jQuery (the library gijgo uses it), but it didn't work.
This is my whole code:
import React from "react"
import $ from 'jquery'
import 'bootstrap';
import { TextInput } from '../Form/Form'
window.jQuery = $;
window.$ = $;
require('gijgo/js/gijgo');
require('gijgo/js/messages/messages.pt-br')
require('gijgo/css/gijgo.css');
export default class DateTimePicker extends React.Component {
componentDidMount() {
this.$dateTimePicker = $(this.dateTimePicker);
this.$dateTimePicker.on("change", this.props.onChange);
this.$dateTimePicker.datetimepicker({
locale: 'pt-br',
uiLibrary: 'bootstrap4',
format: 'dd-mm-yyyy HH:MM',
modal: true,
footer: true
});
}
componentWillUnmount() {
this.$dateTimePicker.destroy("datetimepicker");
}
render() {
return (
<TextInput {...this.props} ref={dateTimePicker => this.dateTimePicker = dateTimePicker}/>
)
}
}
Is there a way to "require something after something else fully loaded?". Am I missing something?
Note 1: yes, I know jQuery + React = bad, but I like this component and I'm porting an old project to React that uses this library, so I figure it would be nice to have it as a React component. My main goal however, is to have some Date Time Picker component that looks like gijgo's and works with React, so I'm open to suggestions.
Note 2: I'm using gijgo through npm (npm install gijgo --save)
Update 1
Note 3: I'm kinda new at React JS development and I'm not quite sure what I'm using for bundling, but the script that runs when I run npm start or yarn start is react-scripts start. Also, the error also shows __webpack_require__ and
779 | };
780 |
781 | // Execute the module function
> 782 | modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
| ^ 783 |
784 | // Flag the module as loaded
785 | module.l = true;
Update 2
I've tried creating a separate file to import jQuery and setting it globally, so I could stop using require and use import instead. Still, I keep getting the same error.
Here's my jQuery.js file:
import jquery from 'jquery';
global.$= jquery;
global.jQuery = jquery;
and here's my updated imports:
(...)
import '../jQuery'
import 'gijgo/js/gijgo'
import 'gijgo/js/messages/messages.pt-br'
import 'gijgo/css/gijgo.css'
(...)
Update 3
It didn't work when I tried using gijgo from <script>, it said datetimepicker is not recognized. I must be doing something wrong, as I'm having a hard time trying to understand how to mix jQuery with React. I think gijgo is a good library and everything. But for this particular case I actually decided to use DateTimePicker from material-ui/pickers.
I am trying to add PrismJS as syntax highliter in my Aurelia app (typescript based) and I am half way there as below
1- Install prismjs
yarn add prismjs
2- add css & code part
<template>
<require from="prismjs/themes/prism.css"></require>
<pre><code class="language-sql">${highlightedSQL}</code></pre>
</template>
3- import the prismjs in the component and call highlite.
import "prismjs";
import prismsql from "prismjs/components/prism-sql";
let Prism; // very weird, I have to declare a global variable, other wise it won't work(typescript error)
#inject(HttpClient)
export class Detail {
highlight() {
this.highlightedSQL = Prism.highlight(data.sql, Prism.languages.sql, 'sql');
}
}
and I am getting this error
Unhandled rejection TypeError: Cannot read property 'highlight' of undefined
what could be the right way to make it work?
ill post my comment as an answer just to have the question closed.
instead of import "prismjs"; and let Prism; you should have import Prism from 'prismjs';
I have an Angular 4.1.1 app that is successfully pulling in leaflet.js to provide maps and map layers etc. I am trying to add a leaflet plugin called browserPrint
I import Leaflet into a Component like this:
import * as L from "leaflet";
import * as browserPrint from "../../../../assets/scripts/leaflet.browser.print.min";
The import statement for Leaflet works great and I can create and display a map.
The error occurs when I try and add the second line for browserPrint.
The angular-cli build throws an error:
ERROR in
/src/app/services/driverLists/driver-lists-map/driverLists.map.component.ts
(8,31): File '/src/assets/scripts/leaflet.browser.print.min.js' is not
a module.
What I have tried:
I added declare var browserPrint: any; to the typings.d.ts
I tried switching the import to:
import "../../../../assets/scripts/leaflet.browser.print.min";
but that just threw tons of errors and broke the maps all together
I tried switching the import to:
import * as BrowserPrint from "../../../../assets/scripts/leaflet.browser.print";
but the error changes to Cannot find module leaflet.browser.print
I have also tried changing the file paths to use the files from the leaflet.browser.print node modules folder. But the same errors are generated.
QUESTION
Can someone help me figure out how to add the leaflet browser print plugin to a leaflet map inside an Angular4+ app?
Thanks in advance.
I saw in the documentation for ngx-leaflet that we should create a ./src/typings.d.ts file and add the below code.
import * as L from 'leaflet';
declare module 'leaflet' {
namespace control {
function browserPrint(options?: any): Control.BrowserPrint;
}
namespace Control {
interface BrowserPrint {
addTo(map: L.Map): any;
}
}
}
It worked for me this way.
I think you want to include the file in the "scripts" array in your angular-cli.json. That should wrap it up in your webpack output, and you won't need to actually import it (as you've said above, that particular file doesn't export anything, so you can't import it anyway).
Documentation here:
https://github.com/angular/angular-cli/wiki/stories-global-scripts
I work on a project that uses React with Typescript. I am trying to import a package and the error I get when I run the file is that the package has no constructor.
I have noticed that error in many packages and I would like to ask if there is a way to make them work instead of trying to find another package that has a constructor.
The package that i am testing right now is called jsPDF
Uncaught TypeError: jspdf_1.default is not a constructor
My code is
import jsPDF from 'jspdf';
export default class DataModelPage extends React.Component<any, any> {
public render(){
let doc = new jsPDF()
doc.text('Hello world!', 10, 10)
doc.save('a4.pdf')
return (
<div>...</div>
)
}
When importing using the following syntax, you are relying on there being a default export in the module:
import jsPDF from 'jspdf';
In many cases there is no default export (I prefer things that way to be honest, as you get to be explicit about your dependencies) - so you need to import using either...
import * as jsPDF from 'jspdf';
Or...
import { justTheThingIWant } from 'jspdf';
(where justTheThingIWant is the name of the thing you want.
Below code worked for me in angular 8 project.
import * as jsPDF from 'jspdf';
Additionally, if someone is trying to export primeNG table content to pdf in landscape mode then may help below codes:
Need to import below library.
import 'jspdf-autotable';
Use below lines of code in .ts file.
const doc = new jsPDF('l', 'mm', 'a4');
doc.autoTable(this.exportColumns, data);
doc.save(this.getFileName('.pdf'));
It may help someone.