Simple Post Editor


#1

Hey All,

Any ideas for a simple blog/post editor for Meteor? I’d like to be able to generate simple HTML posts to store into the DB that contain for instance <p], <b], <blockquote] but will be suitable for someone that does not have any experience programming.

Is there a meteor package for blog posts similar to the wordpress or blogger one? Something that would allow a user to edit the text like a word document and then store the HTML into the database.

thanks!


#2

https://ckeditor.com/ might be applicable.


#3

There’s a package on Atmosphere - Summernote. I’ve used it before - simple and does what you want - even embedded images etc.

https://atmospherejs.com/?q=summernote

https://atmospherejs.com/summernote/summernote - with jQuery and Bootstrap

https://atmospherejs.com/summernote/standalone - standalone - no dependencies


#4

You might want to consider more modern editors that store the rich-text as object. For example the new version of ckeditor, Draft.js / Slate (if you use React) or Quill.js.


#5

Hey,

So I imported CKeditor as an NPM package, and i am importing as such:

import ClassicEditor from '@ckeditor/ckeditor5-build-classic'

And I am trying to all as such:

Template.Blog.onRendered(
  ()=>{
    ClassicEditor.create( document.querySelector( '#mytextarea' ) )
    .then( editor => {
        console.log( editor );
    } )
    .catch( error => {
        console.error( error );
    } );
  }
);

But I am getting the error:

ClassicEditor is not defined
at Blaze.TemplateInstance.Template.Blog.onRendered

Any ideas on this?


#6

Do you have a suitable element in your Blog template? For example:

<template name="Blog>
  <div id="mytextarea"></div>
</template>

Did you do meteor npm i --save @ckeditor/ckeditor5-build-classic?

Note also that in general, using “fat arrow” functions in onRendered (and onCreated) is not a good idea, as it destroys the context of the template.

You can also simplify the logic by using async/await, rather than a Promise chain.

(I just tested ckeditor with Blaze and it works fine).


#7

Hey Rob,

Yes I did, and it is listed in my npm dependencies.

"dependencies": {
    "@babel/runtime": "7.0.0-beta.55",
    "@ckeditor/ckeditor5-build-classic": "^11.1.1",
    "bootstrap": "^4.1.3",
    "jquery": "^3.3.1",
    "meteor-node-stubs": "^0.4.1",
    "popper": "^1.0.1",
    "popper.js": "^1.14.4",
    "simpl-schema": "^1.4.3"
  },

I also created a symbolic link in my imports folder to see if it had the same issue as bootstrap to no success.

I am importing on my main.js file as such:

import ClassicEditor from '@ckeditor/ckeditor5-build-classic';

my Template is as such:

<template name="Blog">
  {{> SectionHeader title="New Post" }}
  <div class="container">
    <div class="row">
      <div class="col coreBG">
        {{#autoForm collection="Blog" id="newPost" type="insert"}}
        <div class="container">
          <div class="row">
            <div class="col">
              {{> afQuickField name="title" }}
            </div>
          </div>
          <div class="row">
            <div class="col">
              {{> afQuickField name="mainImage" }}
            </div>
          </div>
          <div class="row">
            <div class="col">
              {{> afQuickField name="keywords" }}
            </div>
          </div>
          <div class="row">
            <div class="col">
              {{> afQuickField name="excerpt" }}
            </div>
          </div>
          <div class="row">
            <div class="col">
              <textarea id="mytextarea" rows="20" name="post" data-schema-key="post">Hello, World!</textarea>
            </div>
          </div>
          <div class="row">
            <div class="col">
              <button type="submit" class="form-control btn-primary">Add Post!</button>
            </div>
          </div>
        </div>
        {{/autoForm}}




    </div>
  </div>
</div>
</template>

What is the way you are setting the onRendered the way you ran it? I simply copied what was on the CKeditor site.

I am loading my Blog template as a dynamic template from within my Main template that should be an issue though should it?

thank you for the help Rob!


#8
<head>
  <title>ckeditor</title>
</head>

<body>
  {{> Blog}}
</body>

<template name="Blog">
  <div id="mytextarea"></div>
</template>
import { Template } from 'meteor/templating';

import ClassicEditor from '@ckeditor/ckeditor5-build-classic'
import './main.html';

Template.Blog.onRendered(async function () {
  const editor = await ClassicEditor.create( document.querySelector( '#mytextarea' ) );
  console.log(editor);
});

I tried a dynamic template (albeit with a hardcoded template name) and it worked fine.

The “usual” problem with relying on the onRendered is that it doesn’t automatically take care of reactivity. That means that the presence of reactive elements may mean that the onRendered runs (because all static elements can be rendered), but not all the DOM elements in that template may exist at that moment (reactive elements have not been created, because data is not available for them yet).

The template you provided doesn’t appear to have any reactive elements, so I don’t think that will be an issue here.

I don’t think I’ve imported my code any differently to yours, although you haven’t shown where you do your import - it should be in the file(s) where it’s used.


#9

So I was able to get it to work by using a workaround i used for popper.js.

import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
window.ClassicEditor = ClassicEditor;

in a seperate .js file, and then importing that file into the main.js

I am using METEOR@1.7.0.5

I wonder why it seems to be importing with no issues for you…


#10

Did you do the import in a different file? That’s the only reason I can think of for needing to attach it to the global Window object. I’m using Meteor 1.8, but that shouldn’t make a difference here.


#11

No, same file i import everything in.

If I do:

import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating'
import SimpleSchema from 'simpl-schema';
import { ReactiveVar } from 'meteor/reactive-var';

import './popper'
import 'jquery';
import 'bootstrap';

import './templates'

import './lib/routes.js';
import './lib/students.js';
import './templates/js'
import '/client/lib/formmask.js';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
window.ClassicEditor = ClassicEditor;

I get no error.

If I do:

import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating'
import SimpleSchema from 'simpl-schema';
import { ReactiveVar } from 'meteor/reactive-var';

import './popper'
import 'jquery';
import 'bootstrap';

import './templates'

import './lib/routes.js';
import './lib/students.js';
import './templates/js'
import '/client/lib/formmask.js';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';

I get the error… Same file main.js.


#12

Hey Rob,

So when i go to display the post, it displays it as raw HTML, what is the best method to get meteor to convert it to the correct display?

Thank you,
Mike


#13

Nevermind, I see this is as easy as :

{{{post}}}

The three brackets allows it to interpret the html.