0

I am trying to write a "read-only" directive that will transform an input (with ng-model) to a span that has the value of that model. I would like to do this by simply adding "my-read-only" attribute to an element.

See: http://jsfiddle.net/cbW83/4/

angular.module("myapp", []).directive("myReadOnly", [function () {
    return {
        restrict: "A",
        transclude: "element",
        require: "?ngModel",
        priority: 100,
        compile: function (tElem, tAttrs, transclude) {
            var template = angular.element("<span></span>");
            return function (scope, elem, attrs, ngModelCtrl) {
                if (ngModelCtrl && scope.$eval(attrs.myReadOnly) === true) {
                    scope.$watch(function () {
                        return scope.$eval(attrs.ngModel);
                    }, function (newVal) {
                        template.html(newVal);
                    });

                    elem.after(template);
                }
                else {
                    elem.after(transclude(scope));
                }
            }
        }
    }
}]);

<!--Read-Only Directive set to false:-->
<input type="text" ng-model="user.firstname" my-read-only="false" />

I have tried to give the my-read-only directive a higher priority. This allows the textbox to bind to the model, but the span is no longer used.

How can I achieve "toggling" the elements contents and still retain the original element if my-read-only is not set to true? It appears ng-model is being compiled on the element first and this is lost when I transclude.

Patrick
  • 6,828
  • 3
  • 23
  • 31
  • Can you explain your use case? Have you seen [ngReadonly](http://docs.angularjs.org/api/ng.directive:ngReadonly)? You can dynamically set the usual readonly attribute on the input element using it, rather than transforming to a span. – Michal Charemza Dec 17 '13 at 20:16
  • Does ngReadonly keep the textbox but disable it? I need plain old html. The use case being a "nicer" looking display when the user shouldn't be able to enter data rather than a textbox that is not editable. I thought my other option would be to always define two elements where I might want a read-only and use ng-show, ng-if, or ng-switch to decide which to display. I felt like this was "extra" work where I just wanted to transform it to a span. – Patrick Dec 17 '13 at 20:39
  • There is a bit of a difference between 'readonly' and 'disabled', so you might want to use [ngDisbled](http://docs.angularjs.org/api/ng.directive:ngDisabled), and can can [view the differences](http://stackoverflow.com/questions/7730695/whats-the-difference-between-disabled-disabled-and-readonly-readonly-for-te), but both forbid entry from the user. If it's then just a style-issue, then you can set the CSS on the element with the readonly(/disabled) attribute, [as in this fiddle](http://jsfiddle.net/9Lug4/2/) – Michal Charemza Dec 17 '13 at 20:47
  • Definitely ng-disabled="true" like @MichalCharemza said. – Zack Argyle Dec 17 '13 at 20:50

1 Answers1

0

Can change to a span that uses ng-bind as follows:

mod.directive("myReadOnly", function ($compile) {
    return {
        restrict: "A",
        link:function(scope,elem,attrs){
          if(attrs.myReadOnly=='true'){
            var template=$compile('<span ng-bind="'+attrs.ngModel+'"></span>')(scope)
            elem.replaceWith(template);
          }
        }
    }
});

DEMO

charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • This is exactly what I was looking for... I ended up getting it to work with the transclude and priority when I took out the require "?ngModel". This is a lot cleaner though. Thanks! – Patrick Dec 18 '13 at 13:19