ng-model problems in a directive - angularjs

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.

Related

CheckBox.setToggleButton doesn't exist

i have been trying a code found here to add rating bar but i got an error on
cb.setToggleButton(
where the "setToggleButton" method didn't or doesn't exist anymore
any idea if it has been update cause the post i tagged was back from 2014
That method doesn't exist, it should be setToggle(true). Notice in the linked post it just said setToggleButton( without even a closing bracket. Since this was written a while back I'm guessing I just switched a desktop to check the method name and got distracted then forgot to fix that. Hazards of blind coding without the comfort of an IDE.
#devcrp actually wrote the correct answer before but unfortunately he deleted it. If he undeletes it his answer should be accepted.

Secure Angular JS expressions

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.

ng-grid : Why is afterSelectionChange() called twice?

I did not like the answer to this question. To my mind, it has a bad code smell.
I am new to Angular, so I thought I could learn something if I created a Plunk to help that questioner.
My Plunk is http://plnkr.co/edit/fJcew7cGCPzJ0nhIQXjg?p=preview, but there two things which I don't understand.
Please note that I assigned the ng-grid's data two ways - at one fell stroke and row by row. Comment one out & uncomment the other to play around with it.
And be sure to press F12 to see the developer's console log messages.
1) why am I getting TWO ngGridEventData events?
2) why, when I push() row by row am I not getting one ngGridEventData event per push() ?
I am trying to implement master/detail/even more detailed with 3 grids (nothing to do with the current question) and have been googling for a few days now. Many people seem believe that they will get multiple ngGridEventData events and want to know ho to detect that the grid is fully rendered (hence the check in my Plunk).
In short, can anyone explain in detail how ngGridEventData works? Thanks; your answer will help a lot of people.
In a recent Answer here I showed some learnings about this strange behavior. It seems that this routine is called 2 times for reasons I can't really understand (caching maybe?).
You can get this to work if you only react when the data-object is a clone:
if (data.selected === true) {
if (data.isClone) {
numSelectionChanges = numSelectionChanges + 1;
console.log("afterSelectionChange", 'Selection has chanegd ' + numSelectionChanges + ' times');
console.table(data);
}
}
Give it a try, and if you find out why this happens please let me know.
More findings update:
Have a look at this Plunker
I have included the ng-grid.js script directly in the plunker.
If you look at rows 3344-3349 you will find this piece of code:
$scope.$on('$destroy', $scope.$parent.$watch(options.data, dataWatcher));
$scope.$on('$destroy', $scope.$parent.$watch(options.data + '.length', function() {
dataWatcher($scope.$eval(options.data));
$scope.adjustScrollTop(grid.$viewport.scrollTop(), true);
}));
As you can see the there are two watchers applied which looks like a leftover from changes to me. (Although i'm not sure, with me being dumb and those guys being clever). However, if I comment the first line out everything seems to work as expected.
Be carefull when you try this out, because it may break other functionality. I'm not very comfortable with hacking in such a lengthy source code. If someone who is an actual ng-grid team member sees this he can tell me if I found a bug and how to report it. (Never done that before!)

Determining if a specific form field has a required error

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.

AngularJS: is there a debug mode for typos in bindings?

I've just wasted half an hour hunting for what turned out to be...
<select.... data-ng-options="x as x.name for x in customerController_clipped.options"
instead of
<select.... data-ng-options="x as x.name for x in customerController_Clipped.options"
That is, a one-character typo - in this case, a 'clip...' instead 'Clip...'
Sure, it's easy to see it when it's isolated above - but think of this inside huge HTML content, and you now know why I ask:
Is there a way to ask AngularJS to report any failures in names of bindings, to ease our debugging? A simple console logging of this kind of failure would suffice, instead of a silent operation that leaves our components empty...
I can't see anything built in for doing this, though maybe you could raise with angular.js as a feature request, or try writing a pull request for putting an option in $parseProvider? If you want to do this the only way I can see right now is by altering the code in the $parse service which does the interpreting of any expressions.
I've plunked a quick test to see how easy it is. The original code is from angular 1.1.5. Search for ANDYMOD in the angular-1.1.5.js file to see the code I've edited. This basically adds a console.log for whenever the y and z parts of a 'x.y.z' expression are undefined or null, rather than ignoring it.
This is in no way a production-worthy solution, and doesn't work it you want to use ng-csp, but it shows something can be done at least. Maybe you can sub these few lines in if you ever need to test again...

Resources