Search code examples
javascriptangularjsangularjs-directivetinymce-4angular-ngmodel

ui-tinymce directive used into custom directive template : ngModel not updated


I currently have an issue when I call ui-tinymce directive in a custom directive. The custom directive is used to load dynamically links from backend for tinymce advlink plugin (+ load tinymce options object associated with a key passed as an attribute to the directive).

Here is my controller :

module.controller('Ctrl', function ($scope) {
    $scope.test = {
        val: "gfsgfdgh"
    };
});

Here is how I call the directive in HTML:

<tinymce-custom type="minimal" ng-model="test.val"></tinymce-custom>`

And here is my directive :

module.directive('tinymceCustom', function($location, TinyService, Module, GenerateurPage) {
    return {
        restrict: 'E',
        replace: true,
        require:"ngModel",
        scope: {
            ngModel: '='
        },
        link: function(scope, element, attrs, ngModel){

            scope.loaded = {
                modules: false,
                pages: false,
                tinymce: false
            };

            scope.tinyOptions = {};

            var link_list = [];

            var modules = [];
            var pages = [];

            Module.findByOrganisme({}, function (data) {
                data.forEach(function(module) {
                    modules.push({title: module.libelle, value: "/modules/"+module.id});
                });
                link_list.push({title: "Modules", menu: modules});

                scope.loaded.modules = true;
                initTiny();
            });

            GenerateurPage.findByOrganisme({}, function(data) {
                data.forEach(function(page) {
                    pages.push({title: page.titre, value: "/#/generateurPage/afficherPage?id=/"+page.id});
                });
                link_list.push({title: "Pages", menu: pages});

                scope.loaded.pages = true;
                initTiny();
            });

            function initTiny() {
                if (!scope.loaded.modules || !scope.loaded.pages) {
                    return false;
                }

                scope.tinyOptions = TinyService.options(attrs.type);
                console.log(scope);
                scope.tinyOptions.link_list = link_list;

                scope.loaded.tinymce = true;
            }

        },
        template: '<div ng-if="loaded.tinymce"><textarea ui-tinymce="tinyOptions" ng-model="ngModel"></textarea></div>'
    };
});

The problem is that the model passed to ui-tinymce directive is not updated when changing the text with the editor, and the text in the editor is not updated when the model from the controller is changed... BUT, the initial ngModel value is passed to ui-tinymce directive, so I think that is the data binding that is broken. Tried to watch it with $watch but nothing happens. I can't figure how to fix it so I'm now looking for some help...

Thx


Solution

  • Finaly fixed it changing the approach :

    <textarea tinymce-custom="minimal" ng-model="myVar"></textarea >
    

    The final directive :

    module.directive('tinymceCustom', function($location, $compile, $q, TinyService, Module, GenerateurPage) {
        return {
        restrict: 'A',
        priority:999,
        terminal:true, // prevent lower priority directives to compile after it
        scope: true,
        require: ['?ngModel'],
        link: function(scope, el, attrs) {
    
            // default is basic template
            var type = attrs.tinymceCustom ? attrs.tinymceCustom : 'basic';
    
            function loadTinyOptions(name) {
                var loaded = {
                    modules: false,
                    pages: false,
                    tinymce: false
                };
    
                var link_list = [];
    
                var deferred = $q.defer();
    
                var initTiny = function() {
                    if (!loaded.modules || !loaded.pages) {
                        return false;
                    }
    
                    var tinyOptions = TinyService.options(name);
                    tinyOptions.link_list = link_list;
    
                    deferred.resolve(tinyOptions);
                };
    
                Module.findByOrganisme({}, function (data) {
                    var modules = [];
    
                    data.forEach(function(module) {
                        modules.push({title: module.libelle, value: "/modules/"+module.id});
                    });
                    link_list.push({title: "Modules", menu: modules});
    
                    loaded.modules = true;
                    initTiny();
                });
    
                GenerateurPage.findByOrganisme({}, function(data) {
                    var pages = [];
                    data.forEach(function(page) {
                        pages.push({title: page.titre, value: "/#/generateurPage/afficherPage?id=/"+page.id});
                    });
                    link_list.push({title: "Pages", menu: pages});
    
                    loaded.pages = true;
    
                    initTiny();
                });
    
                return deferred.promise;
            }
    
            loadTinyOptions(type).then(function(data) {
                scope._tinyOptions = data;
                el.removeAttr('tinymce-custom'); // necessary to avoid infinite compile loop
                el.attr('ui-tinymce', '{{_tinyOptions}}');
                $compile(el)(scope);
            });
        }
    };
    

    Hope this can help.