How To Source Bootstrap Popover Template From File? - angularjs

I am using angularjs ui bootstrap, and I have my popover template all set up and working. Here is what I have.
directive.html
...
popover-title="Title"
popover-template="'popover.template.html'"
...
A bit lower in the same directive I have the template:
<script type="text/ng-template" id="popover.template.html">
<label>Popup Title:</label>
<span>Popup content</span>
</script>
Now I will need this popover for a few elements, so how can I put it in an actual popover.template.html file in my source tree I just made in the same directory in the simplest way (least lines of code) possible?

The solution was this:
leave the script tags needed for inline tags behind
give the template parameter the full path
create a new file in the desired place, no header needed inside
then add to the element you want popover to work on this:
popover-template="'app/templates/popover.template.html'"
No need for templateCache or any other tricks, the site only sends a single request, even with multiple elements using the same template. It loads on first request.

Related

script tag breaks sightly data-sly tag in author mode

I am using angular with sightly. So I have angular html template surrounded by script tag, which also has sightly attributes like data-sly-resource.
Below example code will give you clear idea.
<script type="text/ng-template" id="example.html">
<section data-sly-resource="${ #path='textOverImage', resourceType='example/components/textOverImage'}" id="textOverImage" >
<div ng-include="'private/textOverImage.html'" data-sly-test="${!wcmmode.edit}"></div>
</section>
</script>
It works fine in non-edit mode , but in edit mode, I can not author data-sly-resource part. It looks like <script> tag is not letting it work roperly because when I remove <script> tag ,than I can author it.
And removing script tag is not an option as well.
So how can I stop script tag form breaking sightly functionality in edit mode?
I ended up doing repetition of code , one for author mode and other for non edit mode.
Below is close resemblance of my solution.
<section data-sly-resource="${ #path='textOverImage', resourceType='example/components/textOverImage'}" id="textOverImage" data-sly-test="${wcmmode.edit}" >
<div ng-include="'private/textOverImage.html'"></div>
</section>
<script type="text/ng-template" id="example.html" data-sly-test="${!wcmmode.edit}">
<section data-sly-resource="${ #path='textOverImage', resourceType='example/components/textOverImage'}" id="textOverImage" >
<div ng-include="'private/textOverImage.html'"></div>
</section>
</script>
As you can see in above code, what to show and when works via data-sly-test="${wcmmode.edit}".
I also tried to to create sightly template for redundant code and than try data-sly-use but now, it works in author mode but sightly can't put template inside <script> tag even though I used # context='unsafe'
There is a workaround based on the Sightly Reference
Put the markup inside a separate html file say mymarkup.html parallel to mycomponent.html
In Component HTML file (e.g mycomponent.html) use <script type="text/ng-template" data-sly-include="mymarkup.html"></script>
In mymarkup.html we can use Sightly tags normally and those would be evaluated/executed normally, we would not even need to specify the # context for variables we would read using use API. The final markup rendered by component mycomponent.html when dragged to page would render something like this below
<script type="text/ng-template">
//mymarkup.html evaluated content here
</script>
In your script tag you could add data-sly-unwrap="${wcmmode.edit}"
This will remove script tag in edit mode allowing you to edit included components but in any other mode the script tag gets rendered.
I found the following mention in Netcentric's AEM Sightly Style Guide:
Then, because the HTML grammar ignores elements located inside a
< script > or < style > elements, no block statement can be used within
them.
Although it's not explicitly stated in the Sightly spec, it makes sense. So your fix is right.

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.

Angular with Play (Scala): ng-include references

Situation
I started an app with Playframework (Scala) and AngularJS v1.3.
(Exactly the template Play Silhouette Angular Seed)
Goal
Loading difference templates using ng-include or a directive.
Problem
Always that I put a reference in Angular code, it doesn't work.
Example:
<div ng-include="'/tpl.html'"></div>
<script type="text/ng-template" id="/tpl.html">
Content of the template.
</script>
Result: works!!
Now, if I put the template tpl.html in a file in the same directory:
<div ng-include="'tpl.html'"></div>
Result: Doesn't work!! (And in other directories, I tried all the possible routes...)
The same problem occurs in directives, if I put the template inside the directory it works well, but if I try to put in another file it doesn't work.
Question
I used Angular in other projects and never occurs something like this. I think that this happens because Scala (language of Playframework) needs to be compiled and the files .scala.html are converted in .html.
How can I create some templates .html and then with ng-include
put the correct reference?
The root directory is the same that index.htmlfile (path: ui/app).
If the file view1.html is in the path ui/app, the ng-include will be like this:
<div ng-include="'./view1.html'"></div>
Because ui/app is the root path.

How to change valid HTML tags that get rendered in ng-bind-html?

I have a text editor (textAngular) that I've modified to limit the number of valid HTML tags I can generate using that tool. Now, I want to only support a limited number of HTML elements (h3, h4, h5, h6, ol, ul) to produce a news story but I want to disable some of the valid HTML rendered by ng-bind-html. Namely, I want to remove , tags as a valid tags because they could have disastrous results for this user generated content.
Is it possible to remove and tags as something rendered by ng-bind-html?
Unfortunately no, it isn't possible to config the valid HTML tags.
The ng-bind-html use the $sanitize service to strip invalid tags/attributes, and you can see in the source code that all the configurations are private.
// Safe Block Elements - HTML5
var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," +
"aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," +
"h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
// Inline Elements - HTML5
var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," +
"bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
"samp,small,span,strike,strong,sub,sup,time,tt,u,var"));
If you really want it, one way you could do is to copy the angular-sanitize.js and modify the valid HTML tags configuration directly.
Please note that if you do it that way, all the ng-bind-html in your entire application will be also affected. If that is undesired, you have to write your own custom directive and inject/use your modified version of $sanitize instead.
If you're into modifying textAngular already, you could modify something around the taCustomRenderers Section of the code and use ta-bind instead of ng-bind-html. They do nearly the same thing except ta-bind runs all the extra renderers.
Custom Renderers Code: textAngularSetup, textAngular - probably in this one you can do your stripping out of unwanted code.

Hide Angular brackets until javascript loaded

I have a few bits of HTML like
<p class="noresults">{{numberOfContacts}} Results Are Available</p>
Is it possible for me to hide {{numberOfContacts}} until Angular has loaded? So it would just say Results Are Available
I've seem some solutions such as hiding the entire body until Angular has loaded, but I'd rather not do that if possible.
Yes, use ng-cloak. Simply add class="ng-cloak" or ng-cloak to an element like this
Using directive <div ng-cloak></div>
Using class <div class="ng-cloak"></div>
It's simply a set of CSS rules with display: none !important and as Angular has rendered your DOM it removes the ng-cloak so an element is visible.
use <span ng-bind="numberOfContacts" /> instead of {{numberOfContacts}}
Sometimes, even if I used the ng-cloak, I could still see the braces for a few seconds. Adding the following style resolved my issue:
[ng-cloak]
{
display: none !important;
}
Please see this link link for more explanation.
Hope it helps :D
This is typically only an issue when working with complex content on really slow devices. In those instances, there can be a brief moment when the browser displays the HTML in the document while AngularJS is parsing the HTML, getting ready, and processing the directives. In this interval of time, any inline template expressions you have defined will be visible to the user. Most devices nowadays have pretty good browsers which are quick enough to prevent this from being an issue. There are two ways to solve the problem.
Avoid using inline template expressions and stick with ng-bind directive.
(Best) Use the ng-cloak directive which will hide the content until Angular has finished processing it. Basically, the ng-cloak directive uses CSS to hide the elements and angular removes the CSS class when the content has been processed, ensuring that the user never sees the {{ and }} characters of a template expression.
One strategy to consider is using the ng-cloak directly to the body element, which will ensure that the user will see an empty browser while AngularJS loads. However, you can be more specific by applying it to parts of the document where there are inline expressions.
I have seen issues with ng-cloak not working when added to an element. In the past, I have worked around this issue by simply adding ng-cloak class to element.
You can use ng-bind instead of expression like
<span ng-bind="data"></span>

Resources