AngularJS ng-model binding doesn't run a custom directive on dynamically added content

1.3k Views Asked by At

I want to create a side-by-side markdown & preview, where the dynamically entered content is rendered as you type.

I have a custom directive for a markdown element, which works on static text, transforming what is in the DOM (raw makdown) into nice HTML (formatted markdown).

Data-binding a textarea to the markdown element will display text as you type, but the directive doesn't work. Raw markdown renders as raw markdown.

I am using showdown.js as the markdown parser. I get the feeling I am missing something simple, but I just can't see it, and it's bugging me.

<div ng-app="myApp" class="container-fluid">
    <div class="span6">
        <textarea ng-model="text"> </textarea>
    </div>
    <div class="span5 border">
      <markdown ng-bind="text">#title
      </markdown>
    </div>
</div>


var myApp = angular.module('myApp', [])

myApp.directive('markdown', function() {
    var converter = new Showdown.converter();
    return {
        restrict: 'E',
        link: function(scope, element, attrs) {
            var htmlText = converter.makeHtml(element.text());
            element.html(htmlText);
        }
    }
});

see the fiddle

I know I could use wmd or pagedowm (as used on this site), but I wanted a minimal interface (no wysiwyg buttons, etc) and code size, and as the rest of the site will be using AngularJS I wanted to use that.

1

There are 1 best solutions below

0
On

try this:

myApp.directive('markdown', function () {
    var converter = new Showdown.converter();

    return {
        restrict: 'E',
        require: '?ngModel',
        link: function (scope, element, attrs, model) {

            var ngModel = attrs['ngModel'],
                render = function () {
                    var html, value;

                    value = ((ngModel) ? model.$modelValue : element.text()) || '';

                    html = converter.makeHtml(value);

                    element.html(html);
                };

            if (ngModel) {
                scope.$watch(ngModel, render);
            }

            render();
        }
    }
});