The original and rather nifty AngularJS directive to enable live content editing of specific elements within a web page, inline and on the fly! Complete with two way binding, dynamic drag and drop functionality and additional helpers for you to easily roll-your-own UI.
Note the demo provides an example using jQuery and Bootstrap 3.
The code is the documentation! It is worth reviewing the demo code itself. It is well commented and demonstrates a good working example of how you can implement and use this directive within a web page or application of your choice.
Reference (see code comments)
Tests (see notes below)
A browser that supports the contenteditable attribute and also supports HTML5 drag and drop specification is required.
Tested working with latest versions of Chrome.
Mileage with older browsers may vary.
Good old fashioned bower install...
bower install ngcontenteditable
This directive can be declared on any element within the DOM. In terms of practicality, its use is intended for block style elements but you are not constained to other style elements (e.g. flexible) by any means.
Drag and drop operations...
Directive declaration is assigned by class attribute. Simply add the "editable" class name to any element to enable editable functionality. Native drag and drop functionality is also provided to "editable" regions (including reads from local file system). Two-way data binding is also provided on "editable" elements.
Example:
<div class="editable" data-ng-model="your.data.model">Some default static content...</div>
If your model data is not available, ngContentEditable will default to whatever static content already exists within your element. This is handy (e.g. for initial design and layout), when for example you are mocking up a web page, or you want to publish with initial static content which the user can later modify in your implementation. As such, subsequent changes will update to your model dynamically.
Any directives which are placed (nested) within an editable region (either implicitly or by user drag drop interaction) will be compiled dynamically. These directives will have access to the following property (as long as they are not defined with isolate scope):
$ngContentEditable (Object)
You can access this property (e.g. during linking phase of a custom directive) to determine if the directive is actively "contained" within an editable area. Linking of directives is also triggered when an editable-component is dragged or dropped into an editable region. This way, your custom directives can be interactive and operate within the context of your "editable" region and allow you to extend functionality for your own specific purposes.
Directive declaration is by class name, simply by adding the editable-component class name to any directives for which you want to preserve scope.
Note - preservation of scope may not be completely reliable (AngularJS). For safety, where the user selects a text range which encompasses any editable-component directives, any subsequent drag events are cancelled (see configService.DISABLE_RANGE_OVER_EDITABLE_COMPONENT).
Directive declaration is by class name, by adding the editable-control class name to any elements you wish to respond to click events to trigger/send supported contenteditable commands to active (cursor) "editable" elements.
The following method must be called to handle drop events on any "editable" elements:
Note data transferred by drag, drop or paste operations is handled (and optionally transformed) based on one or more registered MIME types. If no handler is registered, any drop event will be cancelled/triggers the default paste event (mileage may vary depending on the vintage of your browser).
The registerDropHandler method provides registration of a drop handler for editable elements. In the case of the demo provided, this method is called from the constructor function of directives which apply to specific HTML tags.
The registerDropHandler method takes the following options object as its only argument:
{
types: [], // Array of strings, for each mime type you want to accept (e.g. ['image/jpeg', 'image/png', 'image/gif'])
node: angular.element // Wrapped element which is inserted into editable region (DOM) during uploading phase, if any are associated with this type, for positive user feedback.
format: Function // Callback function which passes single argument (data) to allow manipulation of inserted element on uploading phase completion (e.g. uploaded image final display).
}
The following services are provided for convenience, but primarily for internal use:
editable.utilityService (required by all)
editable.configService (required by editable directive)
editable.rangeHelperService (required by editable directive)
editable.commandHelperService (required by editable-control directive)
Sorry, coverage is a bit sparse at the moment. For now, I've made available some basic sanity testing, validation of two-way data binding on editable regions and some range / selection interaction with editable regions, for good measure.