I've created a directive that wraps a text input field. One of the things I plan to embed in this directive is the validation behavior when it is required, but I'm stuck on one point. You are supposed to be able to refer to the validation errors for an input field using myForm.myField.$error or myForm[myField].$error. However, because my input is created by my directive, it shows up as myForm["{{myDirectiveName"].$error. This is unacceptable because I will have many such fields and I need to distinguish between them.
Plunkr that illustrates this.
The key line that causes problems is this:
console.log( !! form["{{htTextField}}"].$error.required);
What I expect to be able to write is:
console.log( !! form[attrs.htTextField].$error.required);
Many thanks for any help.
I ended up solving this by implementing my own required directive, borrowed from angular's, and customized to modify my own scope variables. Perhaps what I observed in my question is a bug, but I'm not expert enough to fix it in angular's code.
Related
I'm editing an existing code that has a lot of angular js expressions which are being detected as unsafe by our automated testing system. I was able to see the article below that describes my case, but I was not able to get any specific way to solve it (I'm mostly seeing $watch and $apply). I guess what I need to know here is where do I make changes on the code?
Related links:
http://blog.angularjs.org/2016/09/angular-16-expression-sandbox-removal.html
https://docs.angularjs.org/guide/security#angularjs-templates-and-expressions
Sample snippets on my code:
Your code looks perfectly fine. I think what you're missing is the "passing user provided content" portion of that warning.
In the first example the only thing you are passing to $apply is a function that YOU have defined, same as the second example. In the last example you don't pass anything to $apply.
The reason they have these warnings is because $apply can be passed a string to evaluate an expression on $scope.
In the same way that
{{$scope.hello = 'Hello, World'}}
will set the hello property of $scope
$scope.$apply('hello = "Hello, World"')
Will do exactly the same. now imagine you pass user defined content to this
$scope.$apply(userPassedString)
Now you have given a user the ability to run arbitrary javascript expressions in your apply function.
To see exactly what I mean by this (and how this is exploitable), I have created a codepen demo for you here: https://codepen.io/codymikol/pen/bGbzbvp
(You'll have to scroll down in the HTML to see the script, I was lazy and din't link it as a separate JS file \_('__')_/
Also if you REALLY want to understand how the above snippet is able to function (and where I learned about getting the function constructor in such a way) you should watch this video by liveoverflow: https://www.youtube.com/watch?v=DkL3jaI1cj0
This was made back when the AngularJS team was trying to create a sandbox around scope expressions to prevent XSS. There are a bunch of videos detailing different exploits people used to get around the sandbox. Because of how complicated creating a sandbox is and how often it was being exploited they decided to remove it entirely and just warn developers about passing user content in such a way.
im looking to implement a directive to display status messages in my ionic angular app.. the idea is that i define a bunch of standard status messages in my template as follows and it's inspired by the stock ng-switch directive..
<status-bar code="statusCode" onShow="onStatusShow" onHide="onStatusHide">
<status-message when-code="OK" style="calm" timeout="3000">My HTML message</status-message>
...
...
<status-message when-complex style-field="style" text-field="text" timeout-field="timeout" />
</status-bar>
my requirements are these:
status-bar
the directive should bind to $scope.statusCode and depending upon its string value, it should activate one of the sub-directives except the when-complex one..
however, if i assign an object to $scope.statusCode, it should activate the when-complex directive if defined..
the directive also exposes an onShow and onHide callbacks..
when changing the value of $scope.statusCode, the previously active sub-directive should be completely hidden before showing the newly active one.. (animations)
status-message
style and timeout attributes are optional and will default to 'stable' and null respectively..
the timeout attribute will cause this sub-directive to show for a short time before clearing $scope.statusCode..
whereas i can write very simple directives, this one is proving to be a bit beyond me.. ive seen the source of ng-switch and its confusing.. i have tried myself as well but i havent gotten really far with this no matter how much ive tried.. im not posting my code approaches here not for the lack of trying but for the sake of cluttering and relevance..
so i was wondering if maybe someone could come up with a possible basic approach on codepen or plunkr that i can use as a base for expanding upon (since this is just a simplified explanation of what i intend to do with this directive).. or atleast point in the directions i need to go in..
after a night of brain-storming and coding punctuated by coffee and smoke breaks.. ive managed to make it work.. once again keeping ng-switch as a base.. the code is a bit long.. and i changed a few requirements along the way for better usability.. and some requirements like #2 and #3 dont work yet.. but im pretty sure ill make it work as well..
so if anybody is having a similar issue or is interested in my solution.. i can post it here.. :)
I am currently build a set of directives that we will be shipping to customer to use.
Now some of the directives has got required parameter and also some validation on parameters.
Is there some sort of guideline to what a person must do if a required field is not there or a validation failed.
Must you default values,throw exception, or use angularjs exception handling thing.
thanks
you are the one who has written a directive, you must be the one who should answer these questions...
guideline to what a person must do if a required field is not there or a validation failed.
only thing you can help with is making sure that if some required parameters are missing, is give some indication user of the directive, either by some exception logging or console messages etc.
its exactly like how angular tells us how to use ng-change or ng-click for that matter.
I have an issue with angularjs and the email input type.
I want to create dynamic inputs with a directive, but the input type validation might be buggy.
Here is the jsfiddle of my test
http://jsfiddle.net/NPCHr
To avoid some trouble I have to use this trick
element.find('input')[0].type = input.type;
When I had a second character in the input the model field disappears (In the html panel)
I don't know why is this a bug or am I doing something wrong ?
The problem with your directive is not that e-mail validation doesn't work but the fact that dynamic type attribute is not supported by AngularJS (and jQuery BTW). This is due to the fact that IE doesn't allow changing input's type on-the-fly (Changing the <input> type in IE with JavaScript).
This topic was discussed in great details on the AngularJS mailing list, here is the reference: https://groups.google.com/forum/#!topic/angular/Itl-fYzeF18 where someone had exactly the same problem as yours.
The way out of this situation is to manually compile a template using the $compile service. Unfortunately this is not trivial, you can see evidence of some experiments here: https://github.com/angular-ui/angular-ui/pull/191
An alternative, simpler approach is to use ngInclude directive to include different inputs based on their type. Yet another possibility is to use the compile function and manually transform template's markup. But yes, all of those techniques require several lines of non-trivial code.
I am trying to write my first non-trivial directive and am having problems.
What I am trying to do is similar to http://plnkr.co/nYSBnm
This works as intended apart from the two inputs are using the same field. When I try and get them to use the intended fields, by putting
ng-model="record.{{field.name}}"
in the formInput attributes to replace ng-model="record.name" I get an error
Error: Syntax Error: Token '{' is an unexpected token at column 8 of the expression [record.{{field.name}}] starting at [{{field.name}}].
For what it is worth the plunk is at http://plnkr.co/O2uosO27khbcxZEeEb6V
I have looked at various somewhat similar questions on here and stack overflow and so far failed to get anything to work.
I would be grateful for any light anyone can throw on it.
Mark
I had also asked this question on the AngularJS group (I posted here after a day or so of silence on there). Then I got a response from Pawel Kozlowski who pointed out that
ng-model="record[field.name]"
"kind of starts to work" as he put it. There is a plunk here.
Not sure what he meant by his comment but when I put that in a real page and hit refresh I get two copies of the fields (unless I clear the cache), but he certainly solved the stated problem.