Custom Directive with ngClass not working

4,616 views
Skip to first unread message

TsenYing H

unread,
Dec 10, 2012, 10:36:45 AM12/10/12
to ang...@googlegroups.com
I am trying to create a custom directive that wraps an html fragment with a form input field.
The resulting html has an ngClass directive that adds a class if the input element is set to invalid by the ngModelController $setValidity method.

The ngClass directive output by the custom directive does not work.
If I cut and paste the output of the custom directive directly into the html, the ngClass directive works.

What am I missing?

In the ngClass map of class names, I use the ngModelController $invalid method to set the boolean value, 
like so: ng-class="{error: form['b'].$invalid}"
If I add an ngBinding for this in the template, $invalid is true.

The plunkr is here: http://plnkr.co/edit/WoAzzT

The directive is based on the answer by Misko here: http://stackoverflow.com/questions/10629238/angularjs-customizing-the-template-within-a-directive

As background, the purpose of this directive is to display server side validation errors with the corresponding input element and work with Bootstrap CSS to display the html fragment with an error color.




Peter Bacon Darwin

unread,
Dec 10, 2012, 1:58:59 PM12/10/12
to ang...@googlegroups.com
Hi
The main problem you have is that by the time your compile function is called AngularJS has finished collecting directives for this element.  So whatever you do here will not get picked up the the compiler.  Misko's solution is fine because he is pushing only plain HTML into the element.  In your case you need to first compile your string.  But it is complicated to get the ng-model stuff working this way.


--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular?hl=en-US.
 
 

TsenYing H

unread,
Dec 10, 2012, 2:55:46 PM12/10/12
to ang...@googlegroups.com
Hi Peter;
Thanks for the reply.

Is there an alternative approach to do what I am trying to do with a directive?
i.e. take an html fragment with an input element and transform it to 
1. dynamically update with a CSS error class.
2. attach an element to display an error message. (this part works with my original approach)

Thanks;
TsenYing

TsenYing H

unread,
Dec 10, 2012, 3:10:28 PM12/10/12
to ang...@googlegroups.com
Peter;
If I understand your reply, it is problematic to use predefined angular directives inside a custom directive.
Will setting priority on the directive make a difference? Or is it a phasing issue in that as you said; AngularJS has
finished collective directives by the time the compile function is called.
If so, my approach to do what I am trying to do will not work?

Peter Bacon Darwin

unread,
Dec 11, 2012, 3:43:00 AM12/11/12
to ang...@googlegroups.com
You can use Angular directives in a custom directive but you need to be clever about it.  The easiest way is to provide a template, through the template or templateUrl properties of the directive definition object.
If you need to generate your template dynamically, which I "think" is what you are trying to do here.  You have to compile up the html yourself, using something along the lines 
var linkFn = $compile(htmlString);
linkFn(scope);

Pete


--

Pranay Dubey

unread,
Jan 28, 2013, 12:51:03 AM1/28/13
to ang...@googlegroups.com
Hi Peter,
            I am having the same problem and tried what you suggest. The problem is its still not working. Could you please provide a demo fiddle. Will be thankful.

Florian Orben

unread,
Jan 28, 2013, 3:28:54 AM1/28/13
to ang...@googlegroups.com
Hi,

As Peter suggested just use $compile(htmltxt)(scope) to create the element, that you want to append ...

- Florian

Pranay Dubey

unread,
Jan 28, 2013, 4:09:05 AM1/28/13
to ang...@googlegroups.com
and what if i just want  to add an attribute(ng-class) to an element and not the html itself.  I am adding an attribute using $(element).attr(newAttribute); where newAttribute = { 'ng-class': "{....................}" }; The problem here is the attribute is added to the element as per the need but it does nothing. Whereas if i directly use it on the element's html it works fine.

Florian Orben

unread,
Jan 28, 2013, 5:51:10 AM1/28/13
to ang...@googlegroups.com
Hey,

you have to use attrs.$set('attributeName', 'val') (where attrs is the attributes object that is being passed to the linking function), this way angular recognizes the attribute addition/change ...
Modified example from above (see line 16): http://plnkr.co/edit/psEvOJ?p=preview (note the htmlText is no longer being used, it's just to show the attrs.$set usage).

- Flo

Pranay Dubey

unread,
Jan 28, 2013, 6:53:56 AM1/28/13
to ang...@googlegroups.com
Thanks Man. Works Great!!

Paul Gibbs

unread,
Jul 5, 2013, 11:12:46 PM7/5/13
to ang...@googlegroups.com
All –

I've been looking over these examples, and I realized that they don't seem to work when jQuery is present.

From what investigation I've done, when you add form elements through a linking function with jQuery, they are not added to the form object placed on the scope (when using jQuery Lite, they are added, as has been discussed in these examples).

With these two examples (original from above), the only difference is jQuery is included in the second.

Has anyone else seen this before?

Thanks,
Paul

Reply all
Reply to author
Forward
0 new messages