{"id":18307938,"url":"https://github.com/froala/froala-reactive","last_synced_at":"2025-04-05T17:32:04.688Z","repository":{"id":24121452,"uuid":"27509884","full_name":"froala/froala-reactive","owner":"froala","description":"A Meteor reactive template wrapper around Froala WYSIWYG HTML Editor.","archived":false,"fork":false,"pushed_at":"2021-06-08T12:12:20.000Z","size":69,"stargazers_count":25,"open_issues_count":4,"forks_count":5,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-03-21T08:11:10.877Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://froala.com/wysiwyg-editor","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/froala.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-12-03T22:01:56.000Z","updated_at":"2024-06-25T01:40:10.000Z","dependencies_parsed_at":"2022-08-22T11:10:22.171Z","dependency_job_id":null,"html_url":"https://github.com/froala/froala-reactive","commit_stats":null,"previous_names":[],"tags_count":81,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/froala%2Ffroala-reactive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/froala%2Ffroala-reactive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/froala%2Ffroala-reactive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/froala%2Ffroala-reactive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/froala","download_url":"https://codeload.github.com/froala/froala-reactive/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247374935,"owners_count":20928915,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-05T16:06:02.639Z","updated_at":"2025-04-05T17:32:04.188Z","avatar_url":"https://github.com/froala.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Froala Reactive WYSIWYG HTML Editor\n\n\u003eFroala-Reactive provides a template-based, reactive wrapper around the [Froala WYSIWYG HTML Editor](https://froala.com/wysiwyg-editor/pricing), designed to play nicely with [Meteor Framework](https://www.meteor.com/) client-side templates.\n\n\u003eNote that Froala Editor requires a [license for commercial use](https://froala.com/wysiwyg-editor/pricing).\n\n## Breaking Change to v2\n\nVersion 2.0.0 of this package onwards uses the upgraded Froala Editor V2.  You will need to update and revise all Froala Editor API usage in your code (e.g. events, additional Froala Editor method calls, options) as described in the [V2 migration guide](https://www.froala.com/wysiwyg-editor/docs/migrate-from-v1).  Please contact Froala directly for help, unless you really think there is an issue in the reactive wrapper code in this package(!)\n\n## Installation\n\nYou can install Froala-Reactive using Meteor's package management system  The Froala-Reactive package automatically includes the separate froala:editor package which provides the actual Froala Editor javascript library:\n\n```bash\nmeteor add froala:editor-reactive\n```\n\n## Basic Usage\n\nFroala-Reactive provides a [Template inclusion tag](https://github.com/meteor/meteor/blob/devel/packages/spacebars/README.md#inclusion-tags) which wraps the underlying Froala-Editor jQuery plugin.  In it's simplest form, add it to your template like this:\n\n```html\n\u003ctemplate name=\"myTemplate\"\u003e\n  \u003cdiv\u003e\n    {{\u003e froalaReactive getFEContext}}\n  \u003c/div\u003e\n\u003c/template\u003e\n```\n\n```javascript\nTemplate.myTemplate.helpers({\n  getFEContext: function () {\n    var self = this;\n    self.myDoc.myHTMLField = 'Hello World !';\n    return {\n      // Set html content\n      _value: self.myDoc.myHTMLField,\n      // Preserving cursor markers\n      _keepMarkers: true,\n      // Override wrapper class \n      _className: \"froala-reactive-meteorized-override\",\n\n      // Set some FE options\n      // toolbarInline: true,\n      initOnClick: false,\n      tabSpaces: false,\n\n      // FE save.before event handler function:\n      \"_onsave.before\": function ( editor) {\n        // Get edited HTML from Froala-Editor\n        var newHTML = editor.html.get(true /* keep_markers */);\n        // Do something to update the edited value provided by the Froala-Editor plugin, if it has changed:\n        if (!_.isEqual(newHTML, self.myDoc.myHTMLField)) {\n          console.log(\"onSave HTML is :\"+newHTML);\n          myCollection.update({_id: self.myDoc._id}, {\n            $set: {myHTMLField: newHTML}\n          });\n        }\n        return false; // Stop Froala Editor from POSTing to the Save URL\n      },\n    }\n  },\n})\n```\n\nWhere:\n\n* The \"myTemplate\" template has a data context that contains a 'myDoc' property, which itself contains '_id' and 'myHTMLField' properties.\n* We use a helper to build the data context object to pass to the froalalReactive template.\n* We set some [Froala Editor options](https://www.froala.com/wysiwyg-editor/docs/options)\n* The `\"_onsave.before\"` property provides a callback function to handle the Froala-Editor [save.before](https://www.froala.com/wysiwyg-editor/docs/events#save.before) event.\n* The `_value` argument provides the HTML string that you want to display and edit\n\nHere, we are triggering the update of the underlying 'myDoc' document record in the 'myCollection' collection when the Froala Editor 'beforeSave' event triggers.  We could easily have used the 'blur' or 'contentChanged' events instead.\n\nThe final line in the callback stops Froala Editor from generating its own AJAX call to post the updated HTML contents, because we have used the awesomeness of Meteor to do that for us instead.\n\nNote that Froala-Reactive *does not* automatically update the edited `_value`, you\nhave to provide your own Froala-Editor event handler(s) to do that.\n\nHowever, Froala-Reactive *will* reactively update the displayed `_value` HTML immediately if you have assigned it to a data context property or template helper function which changes its value any time after the template has rendered (e.g. if the underlying collection document is updated from the server, or another action on the client).\n\n\n## Events\n\nYou can provide callbacks for any of the Froala-Editor [events](https://froala.com/wysiwyg-editor/docs/events) by specifying `_on\u003cevent name\u003e` arguments in the `{{\u003e froalaReactive}}` inclusion tag with name of template helper functions that must return a function with the expected Froala-Editor event function signature.\n\nFor example, to set up a callback for the [image.beforeUpload](https://froala.com/wysiwyg-editor/docs/events#image.beforeUpload) event:\n\n```html\n{{\u003e froalaReactive ...  _onimage.beforeUpload=imagePasted ...}}\n```\n\n```javascript\nTemplate.myTemplate.helpers({\n  imagePasted: function () {\n    var self = this;\n    return function (editor, img) {\n      // Do something\n    };\n  }\n});\n```\n\nNote that the event name used in the `_on\u003cevent name\u003e` argument name must be exactly the same as used in the Froala Editor `on('\u003cevent name\u003e', function ....)` callback declaration. \n## Options\n\nSimilarly, you can pass any of the Froala-Editor [options](https://froala.com/wysiwyg-editor/docs/options) to the underlying Froala-Editor plugin object, by simply declaring them as arguments to the `froalaReactive` inclusion tag.  Also, if any of these option argument values are set to values on your template's data context, or from return vaues from template helpers, Froala-Reactive will call the Froala Editor `option` setter method to change them if any of them change values once your template has been rendered.\n\n```html\n{{\u003e froalaReactive ... language=getLanguage ...}}\n```\n\n```javascript\nTemplate.myTemplate.helpers({\n  getlanguage: function () {\n    return Session.get('language');\n  }\n})\n```\n\nNote that option values cannot be changed after initialisation (e.g. [inlineMode](https://froala.com/wysiwyg-editor/docs/options#toolbarInline)) ... please refer to the Meteor-Editor documentation.\n\n#### _className wrapper div class name override\n\nIf you have multiple instances of `{{froalaReactive}}` in the same template, and you need to target the underlying FroalaEditor instance in each, override the wrapping `div` class name in each instance to be a unique value, by specifying the `_className=fooClass` context property.\n\n#### _keepMarkers\n\nIf you preserve the current cursor position marker when saving the FroalaEditor contents (using `html.get` keep_markers method flag), then also set `_keepMarkers=true` context property. This ensures that FroalaReactive's comparison between current and new contents takes the market html into account.\n\n## Methods\n\nYou can invoke any of the Froala Editor [methods](https://froala.com/wysiwyg-editor/docs/methods) directly on the `editor` object in your Froala Editor event callback functions.  See above for an example of calling `editor.html.get()`.\n\n\n## Gotchas\n\n1. Remember that you must provide one or more `_on` callbacks to handle changing the froalaEditor contents, if you want use the Meteor Framework to do so.\n2. If two or more users are actively editing the same underlying state (e.g. the same property of the same document in a collection), and you have set up a contentChanged event handler, or an autosaving Froala Editor, then the content will keep changing.  Their local caret cursor will keep resetting and jumping around.  To avoid this, you may want to implement some kind of locking mechanism, to only one user can initiate an edit session at a time.  To do this properly requires implementing something like Operational Transform!\n3. The Froala Editor V2 API has renamed some methods with dotted notation (e.g. [save.before](https://www.froala.com/wysiwyg-editor/docs/events#save.before).  This means you cannot set their values directly in a blaze template (it throws an error in the blaze compiler if you try something like `{{froalaReactive onsave.before=doSave}}`).  Instead, you will have to create a template helper function that builds the complete context JSON object ... see the example given in the Basic section above.\n\n## Acknowledgements\n\nThis package is based on the implementation of the [x-editable-reactive-template](https://github.com/davidworkman9/x-editable-reactive-template) package.\n\n## License\n\nThis package is released under the MIT License (see LICENSE). However, in order to use Froala WYSIWYG HTML Editor plugin you should purchase a license for it.\n\nFroala Editor has [3 different licenses](https://froala.com/wysiwyg-editor/pricing) for commercial use.\nFor details please see [License Agreement](https://froala.com/wysiwyg-editor/terms).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffroala%2Ffroala-reactive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffroala%2Ffroala-reactive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffroala%2Ffroala-reactive/lists"}