ng-include not recognizing appended version number - angularjs

I appended version number to all of my templates under routeProvider so that it will load the latest templates every time the version number changes. It works just fine until I noticed that there is still one more template that needs to be appended, and that`s the sidebar-menu that was found on ng-include. I appended version number to it using this code
<div ng-include = "'views/sidebar-menu.html?v={{VERSION_NO}}'"></div>
I successfully changed the version number, however, it is still not reflecting my latest changes to the menu template. Any idea why this doesn`t work?

Reason it didn't worked is you put variable name inside single quotes so it will be considered as string .
Try:
<div ng-include = "'views/sidebar-menu.html?v='+VERSION_NO"></div>
This will parse your variable and give you required version.You don't need paranthesis {{ }} as it evaluates expression, hence will evaluate your variable automatically

ng-include takes an expression, so you don't need interpolation syntax {{. Instead, you can set the full string on the scope.
$scope.sidebarTemplate = 'views/sidebar-menu.html?v=' + VERSION_NO;
Now you can do <div ng-include="sidebarTemplate">

Related

pass cmsfn value to a scope variable angularjs

I'm trying to pass a variable to angularjs from cmsfn. Did anyone managed to do it already?
<div ng-controller="someController">
[#assign currentNode = cmsfn.asJCRNode(content)]
[#assign rootPageNode = cmsfn.root(currentNode, "mgnl:page")!]
<div style="display: none">{{myVar='${rootPageNode}'}}</div>
</div>
In the above code, when i try to use myVar in angular, its value is empty.
So first, reduce your FM code to single line:
[#assign rootPage = cmsfn.root(content, "mgnl:page")!]
This way, what you get back is still ContentMap and not Node which is easier to manipulate in the template.
Second, get the name of the page (if that is what you want):
${rootPage.#name}
You can find list of other special properties of content map at the bottom of this page
Now, last about the angular part, what you have in your template is just angular expression, "print statement" if you will, which will not assign variable. You need to do the assignment using $scope.myVar=... in the someController controller itself. Which means that the .js file itself needs to be freemarker template.

AngularJS Protractor: select div with ng-show directive

I need to access to a div with a ng-show directive WITHOUT using xpath
<div ng-show="my_error && dirty_field">
Custom error message.
</div>
I tried these but it doesn't work properly
element(by.css('[ng-show=my_error && dirty_field]'));
and
element(by.model('my_error && dirty_field'));
How can I do?
Just to add few points here.
First of all, you definitely need the quotes around the ng-show value in this case:
element(by.css('[ng-show="my_error && dirty_field"]'));
This is because the value contains non-alphanumeric characters. See this related thread:
CSS attribute selectors: The rules on quotes (", ' or none?)
Also, I don't think you should use the dirty_field part in your locator. This sounds like a more technical variable used in the form validation logic. I'd use the "contains" check instead to check the my_error part only (note how I've removed the quotes in this case - the value is alphanumeric):
element(by.css('[ng-show*=my_error]'));
Also note that you can use the $ shortcut instead of element(by.css()):
$('[ng-show*=my_error]');
You cab deal with the properties this way in doing protractor testing.
element.all(by.css('[ui-sref="about_us"]')).first();
element(by.css('[ng-click="clickme()"]')),
element(by.css('[ng-show*=show_me]'));

Decompile angular elements

We have a angular grid written by some guys here at work, the entire company uses it.
A td-cell could look like this
<td typeahead-cell="location as location.Name for location in getApiLocations($viewValue, mapping)" ng-model="mapping.selectedLocation">
{{mapping.getLocationNames()}}
</td>
The typeahead-cell directive will execute some custom code on the td, what it does is hookup some code so that if you double click or write in the cell it will go from display only to (in this case) typeahead. It does this by taking the html in the td cell (The td cell is already compiled by angular), wrap it with some custom code that does above functioanlly and then call $compile on the entire thing. This works with expressions above like {{mapping.getLocationNames()}} because they do not change when compiling so it can be compiled any number of times.
The problem I face now is that I try to use a more complex expression with ng-repeat. Problem is the first compile (Done directly by angular-core) will change html from example
from
<span ng-repeat="location in mapping.locations">...</span>
to
<!-- ngRepeat: location in mapping.locations -->
Then when our custom grid code executs it will try to compile the code above which will result in an empty since it compiles against a html comment.
This is the code that breaks
$element.html($compile(displayElement.html($element.html()))($scope));
$element is the td-cell that contains my orignal code that, when doing $element.html() it will take compiled code and try to use that. Wont work. Displayelement is a wrapper that will show when we are in displaymode.
I either need to decompile $elementbefor edoing $element.html or somehow move the content of the $element (td cell) compiled and hooked up.
Any ideas?
edit: I have somewhat solved it, doing this
$element.children().appendTo(displayElement);
displayElement.appendTo($element);
This will take the children from the td-cell and add them to the displayElement without actually breaking the original $compile. jQuery.children cant move <!-- comment --> elements so if you have an expression with ng directives like my repater above you need to wrap it in a dummy element like
<span><span ng-repeat="location in mapping.locations">...</span></span>
Any workaround for this?
Instated of that line if you can check with this
//Store it first on a variable if blank
var html;
if(!html) html = displayElement.html($element.html());
$element.html($compile(html)($scope));
Hopefully it will work. May be you need to manage the scope of the variable.
Final solution is this
$element.contents().appendTo(displayElement);
displayElement.appendTo($element);
It's very important to use contents and not children because childrenwill ignore text nodes which will not include the comments generated by ng-repeat directive.

display current value of ng-class in AngularJS

I have to track down a bug related to work of ng-class (sometimes it adds new value without removing old).
So I need a quick reference to see it's current value.
Is there any short (or not) way to bind that to the content?
I mean something like this:
<div ng-class="something">
{{ngClassValueDisplayedHere}}
</div>
I had exactly the same problem with ng-class not removing old value. After days of investigation it turned out that it was ngAnimate who was messing with class changes. removing it from angular module dependencies solved the problem (Angular 1.3).
ng-class can bind to many different things. From the documentation:
Expression to eval. The result of the evaluation can be a string representing
space delimited class names, an array, or a map of class names to boolean
values. In the case of a map, the names of the properties whose values
are truthy will be added as css classes to the element.
So in your example, just display whatever your something is. It's supposed to be an angular expression, which can be evaluated like any other with double-curlies. This will help you debug your ng-class
<div ng-class="something">
{{something}}
</div>
Demo
In case someone else stumbles upon this problem like I did just recently with angular version 1.5.8: https://github.com/angular/angular.js/issues/14582
P.S. Update to 1.5.11 solved the issue related to ngAnimate, prior versions still had the same issue.

Stop AngularJS inserting <span class="ng-scope"></span> using ng-include

I'm using the Foundation layout framework, which automatically floats the last sibling of .column to the right and I really appreciate this is a behaviour. However, AngularJS takes it upon itself to insert span.ng-scope after every div.column, which somehow causes browsers to consider the last span the last sibling of .column (even though it is not).
Specifically the css in Foundation responsible for this is:
[class*="column"] + [class*="column"]:last-child { float: right; }
As I understand it, [attribute*="substring"] should select only siblings that match, so, for the above, only elements whose class attribute contains column (including columns). I would think a span tag whose class attribute that does not contain column should not match (and thus be ignored by :last-child). However, this does not seem to be the case.
Regardless, the span is causing the problem:
Angular buggering it up (jsfiddle)
Works fine without Angular (same jsfiddle, no ng-include)
Is there a way to configure angular to stop inserting those span tags? I would, begrudgingly, modify the css selector to somehow ignore all span tags; however I might eventually need/want to use a span tag.
Since you indicated the div can be moved inside, this works:
<ng-include src="'main.tmpl'"></ng-include>
Then in your template:
<div class="row">
<article id="sidepanels" class="four columns">
...
</div>
I'm not aware of any way to prevent angular from inserting the span tags (I think it keeps track of scopes that way -- for garbage collection).
Also you can try my version of include directive that does not creates a scope: Gist source.
As no scopes are created, AngularJS should not create additional element to mainain scope (it actually use data attributes to store link to scope).

Resources