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.. :)
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.
JS Bin here
This article describes a clever way to see if your (pure Angular) form model has changed since the initial load. In my mind it's a more accurate test of $dirty/$pristine. This allows us to do things like hide the "Save" button for a form if the model hasn't changed, even if the user has typed then deleted text.
So the question is, how can we do this with angular-formly? My hunch is that onChange for each field might be a good starting point, but I'm having a lot of trouble putting together the rest of the solution.
Hope the question makes sense. Any ideas would be very welcome. Thanks!
This might work in a limited capacity:
scope.initialValue;
var listener = scope.$watch(function(oldVal,newVal){
scope.initialValue = oldVal
listener();
})
atinder was correct in that the pure Angular approach actually works fine with angular-formly. I've created a working JS Bin here.
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.
I'm just curious but I was wondering if there was a way to target an element and grab it's controlling directive. ie. something like angular.element('#id').directive().
If there's no direct way of doing this, I have a backup but I think it would be rather neat.
Thanks.
I think I may have posed the question incorrectly and confused people. All I was looking for was the .scope() method which you can call off an angular.element() selection. Seems to work nicely.
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