What is the use of .scope() in AngularJS? - angularjs

What is the use of .scope() in AngularJS? I have seen some code examples using this but I am not quite sure what the use is, and I have been unable to find an answer in SO posts and in AngularJS documentation. For example:
var scope = angular.element(document.getElementById("MainWrap")).scope();
Is this somehow similar to use of $digest or $apply?

Here an example of what I use it for every day:
Open Console in dev tools.
Right-click an element in your page that is managed by AngularJS, select inspect element option
Now write in console: angular.element($0).scope()
You just got a scope of said element as that element sees it. You can go up through the parent, manage its content (don't forget to $apply() afterward to test the change, otherwise, it won't bind) or do similar things you can in console with any JS object.
There are more uses for it for sure internally, but this one I find really helpful when debugging. So in relation to $apply() it is and is not linked to it, depending what you use it for.

Related

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.

Testing Angular with Protractor

I am new to Protractor. Can anyone advise me how to deal with Promises and how to know what methods I can call on an element?
For example, I may access an element like: var element = element(by.css('.fileName'));
That brings back a promise correct? So, when can I act on it and how do I know what I can actually do to?
In ruby for example, I can do element.methods and see all that I can do for this object.
Please advise
Thanks,
JC
I have been working on the new protractor documentation. It should be published to http://protractortest.org soon. In the meantime take a look at this:
http://angular.github.io/protractor/#/api?view=ElementFinder
See the documentation: https://github.com/angular/protractor/blob/master/docs/api.md#elementfinder
The ElementFinder can be treated as a WebElement for most purposes, in particular, you may perform actions (i.e. click, getText) on them as you would a WebElement.
So, beasically, you can call click() (for example) on the element (the promise) as soon as it's returned. This will tell protractor that, once the element has actually been found, it will have to click on it.

Putting presentation data in angular controller?

Got a webapp I'm building in Angular.
This app walks a user to authorizing accounts, presenting specific instructions based on the users choices.
I've implemented this as HTML that is shown or hidden based on values in the model, so for 3 different choices, I have 3 different sets of HTML sections that are similar but with different texts.
In the spirit of DRY, I should instead have one set of HTML sections, and instead switch the text based on the values of the model. This means putting text data inside the model, including small snippets of markup, like anchor and strong tags.
Does putting presentation data into the controller violate the principals of Angular?
There are quite a number of options to avoid repeating code depending on what you are looking to do. The following ideas are things I would consider and use when they make sense (I placed these from simple to complex, so you probably can skip the first few):
ng-bind -- Put it on a span/div. Simple & works to bind the model to the display
ng-switch, ng-if, ng-hide, ng-show -- Work to conditionally show an element
custom directive -- use this when you want to alter the behavior of an element or if you want to alter the dom based on a template. If you use "ng-transclude" the contents of the element you template will be included in the result. This can be very elegant but it works best when you have a single format. I can provide examples but angular's documentation also has excellent examples.
service -- I generally use this just to provide data only. This could be via a restful api and $resource or via $http calls. Either way, I wouldn't recommend doing much more than load/save data here.
$scope method -- In other words:
$scope.myMethod = function(x,y,z) { /* code making decisions based on the model */ }
Then you can call this method from one of the previous either via a prebuilt directive (ng-show, etc) or via a custom directive that manipulates the dom for how you expect it to be.
ng-bind-html -- Last option I know to suggest is to use this directive combined with the $sce service to bind whatever you want to the DOM. If you are binding something with angular code in it - make sure to use the $compile service as well. I generally don't favor this approach except as a last resort because it makes it harder to find where elements in the DOM are coming from and it can make debugging + testing a real pain. That said, these tools wouldn't exist if people didn't need them.
I'm sure that this isn't complete and maybe others have suggestions but that is where I would start. Best of luck!
I would put the text data in a separate angular service. This article gives an example: http://joelhooks.com/blog/2013/04/24/modeling-data-and-state-in-your-angularjs-application/
Then if you decided at some point to move it to some other storage, your service would still be the single access point for the rest of the app.

AngularJS and ui-sortable(branch 1.2): ng-mouseover breaks after sorting

I upgraded my App to AngularJS 1.2 and so also switched to ui-sortable v 1.2.
The sorting is implemented for Accordion-Groups (from ui-bootstrap). With the master-tree version of sortable i could listen to ng-mouseover/ng-mouseleave inside the accordion headers but with the 1.2 version, the mouseevents are only listening as long as i haven't done any sorting. After performing any change to the sortorder, the mouseevents become deaf...
Here's a Plunker: http://plnkr.co/edit/n8yms9pb7uJp77zZ9LFK?p=preview
Can anybody give me some advice how to fix that?
Thank you
Identity Problem.
elementInsertedByDropping !== elementSelectedAndDragged
In the console, one can verify the assertion above. So that narrows down the category of problem to a relatively familiar one.
I'm learning Angular myself, and I'm also having trouble with ui-sortable; please don't regard my opinions as definitive. However, I believe that the problem is that the $watch listeners need to be re-bound to the new element, as it is being created asynchronously outside of Angular.
The "ng.$rootScope.Scope" documentation describes this situation somewhat clearly in the $apply section. If I am correct, you would need to either $scope.$apply(...) code in your controller, or [preferably] write a custom directive that handles the insertion.
Fortunately, it seems that jQuery-ui-sortable's "update" event can be easily used in a custom directive to ensure that the element is bound. I found that bloggers respectTheCode and Michal Ostruszka discuss the problem of writing jQuery-ui-sortable directives in fairly clear terms; so does a fellow named Greg Gigon and several others, but I'm only allowed to offer you two links at this point.
If I can provide more precise information at a later point, I will revise this answer; I'm still learning this stuff myself, and I would like to know how to do something quite similar.
[edit: I'm not familiar enough with Angular-UI-Sortable to know whether this is a bug or simply missing functionality.]
Looks like a bug in ui-sortable.
My guess: It seems to be losing the bindings from the event directives, probably because it's destroying the old DOM elements and creating a new ones without re-attaching the scope with $compile. I'd save this plunk and submit and issue on their GitHub repository

How to process a template and remove all bindings from it?

I need to create a page with AngularJS that will display thousands of log entries. These entries will be created with the help of Angular templates, but, since they are unchangeable once printed, I would like to have the bindings removed from the resulting entries.
Is this possible? I looked at $compile (keeps the bindings) and $interpolate (doesn't do directives if I understood correctly, only does {{ }} ) and haven't found an answer to my question.
How would you approach such a problem?
You can use the directives defined in the Bind Once library in order to perform binding for immutable data.
I didn't find an answer to my problem, the problem though can be circumvented with an "infinite scroller" such as the one described here: https://medium.com/p/463bc649c7bd that "disappears" log entries that aren't in the viewable window.

Resources