Search code examples
angularjswysiwygdirectiveredactor

Integration of Redactor WYSIWYG in an AngularJs directive


I try to integrate The beautifull WYSIWYG Redactor (http://imperavi.com/redactor/) in an custom AngularJS directive.

Visualy it works, but my custom directive is not compatible with ng-model (and I don't understand why)

This is how you can use my directive :

<wysiwyg ng-model="edited.comment" id="contactEditCom" content="{{content}}" required></wysiwyg>

And this is the directive code :

var myApp = angular.module('myApp', []);
myApp.directive("wysiwyg", function(){

var linkFn = function(scope, el, attr, ngModel) {

    scope.redactor = null;

    scope.$watch('content', function(val) {
        if (val !== "")
        {
            scope.redactor = $("#" + attr.id).redactor({
                focus : false,
                callback: function(o) {
                    o.setCode(val);
                    $("#" + attr.id).keydown(function(){
                        scope.$apply(read);
                    });
                }
            });
        }
    });

    function read() {
        var content = scope.redactor.getCode();
        console.log(content);
        if (ngModel.viewValue != content)
        {
            ngModel.$setViewValue(content);
            console.log(ngModel);
        }
    }

};

 return {
     require: 'ngModel',
     link: linkFn,
     restrict: 'E',
     scope: {
         content: '@'
     },
     transclude: true
 };
});

And finally this is the fiddle -> http://fiddle.jshell.net/MyBoon/STLW5/


Solution

  • I made one based on Angular-UI's TinyMCE directive. This one also listen to format button clicks. It also handles the case when the model is changed outside the directive.

    directive.coffee (sorry for the coffeescript)

    angular.module("ui.directives").directive "uiRedactor", ["ui.config", (uiConfig) ->
    
      require: "ngModel"
      link: (scope, elm, attrs, ngModelCtrl) ->
        redactor = null
    
        getVal = -> redactor?.getCode()
    
        apply = ->
          ngModelCtrl.$pristine = false
          scope.$apply()
    
        options =
          execCommandCallback: apply
          keydownCallback: apply
          keyupCallback: apply
    
        scope.$watch getVal, (newVal) ->
          ngModelCtrl.$setViewValue newVal unless ngModelCtrl.$pristine
    
    
        #watch external model change
        ngModelCtrl.$render = ->
          redactor?.setCode(ngModelCtrl.$viewValue or '')
    
        expression = if attrs.uiRedactor then scope.$eval(attrs.uiRedactor) else {}
    
        angular.extend options, expression
    
        setTimeout ->
          redactor = elm.redactor options
    ]  
    

    html

    <textarea ui-redactor='{minHeight: 500}' ng-model='content'></textarea>