5

I'd have a directives with a large form with some fields that are required and some that are not. The required fields are marked with required attribute.

I want to pre-pend all the inputs with <span class='something'>*</span> Basically something like this: $("input[required]").prepend(<span class='something'>*</span>)

My still limited understanding of angularjs points me to the compile function of my directives but I am lost when I get there.

Disclaimer: my gut feeling is telling me that doing something like that is not really "the angular" way - that's ok, regardless of whether I end up using this technique or not I'd like to know how to do that. That said I welcome more "angular" suggestions as well.

Thank you!

americanslon
  • 4,048
  • 4
  • 32
  • 57
  • How is the required attribute being added to the inputs? – dnc253 Apr 24 '14 at 17:53
  • Declaratively. It's in the HTML of the directive. – americanslon Apr 24 '14 at 18:02
  • Right, but it's not being dynamically added? If it's not dynamic, you already know which fields are required and thus can add the `*` where you add the `required` attribute. If it is dynamic, then I'm wanting to know how they are being dynamically added. – dnc253 Apr 24 '14 at 18:07
  • No they are not dynamically added, you are right I could just go and add the asterisk myself. I don't want to do that. I'd like to work so the act of marking something `required` makes the asterisk appear automatically – americanslon Apr 24 '14 at 18:10
  • Ok, I get where you're coming from, answer forthcoming. – dnc253 Apr 24 '14 at 18:12

3 Answers3

11

Whenever DOM manipulation enters the conversation, a directive is the way to go. You're wanting to prepend a * to any inputs with a required attribute, so you want to create a directive from the required attribute. Something like this:

myModule.directive("required", function() {
   return {
       restrict: 'A', //only want it triggered for attributes
       compile: function(element) {
          //could add a check to make sure it's an input element if need be
           element.prepend("<span class='something'>*</span>");
       }
   }
}
dnc253
  • 39,967
  • 41
  • 141
  • 157
  • Neat! And angular-y. Thank you. – americanslon Apr 24 '14 at 19:04
  • 2
    This does not seem to work in `` , however works fine on a `
    `. Please advise.
    – americanslon Apr 24 '14 at 19:37
  • Not sure why that would make a difference. Put a fiddle together that reproduces the problem, and I could take a look. – dnc253 Apr 24 '14 at 19:50
  • Looks like for input you need `.after` and `.before` instead of `.prepend` and `.append`. Don't know why yet. – americanslon Apr 24 '14 at 19:54
  • @americanslon, it doesn't work for input because input elements have no content. Even if you manually write `Something Here`, the browser will ignore the contents. `.append()` and `.prepend()` both insert contents *inside* the current element, so won't work for inputs. Same reason why [`input:before` doesn't work](http://stackoverflow.com/a/4574946/1366033). As you noted, you should be fine using `.after()` instead. Although [.before() will create an infinity loop](https://github.com/angular/angular.js/issues/5663) – KyleMit Jan 28 '15 at 17:36
2
input[required], select[required] {
    background-image: url('/img/star.png');
    background-repeat: no-repeat;
    background-position: right;
}

Image has some 20px space on the right not to overlap with select dropdown arrow

Image is here

Toolkit
  • 10,779
  • 8
  • 59
  • 68
0
committeeApp.directive("requiredStar", function ($compile) { 
return { 
    restrict: 'AE', 
    require: "^form", 
    link: function (scope, element, attrs, ctrl) { 
        var varName = ctrl.$name + "." + attrs.name + ".$error.required";           
        var a_input = angular.element($compile('<span style="color:red;" ng-show="' + varName + '" >&#10033;</span>')(scope)); 
        element.parent().prepend(a_input); 
    } 
}; 
Makatun
  • 947
  • 10
  • 11