How do I load an Image from $templateCache using Angular 1 - angularjs

I have a plnkr and the story is long but it comes down to I need to be able to use an image from the templateCache. I try to do this using ng-src like this...
$templateCache.put('img/help/copy_icon', '://www.drupal.org/files/issues/sample_7.png')
...
template: '<img ng-src="{{url}}">'
However this doesn't work and I get...
copy_icon':1 GET https://run.plnkr.co/ZyTH7LFhPLhdQpCI/'img/help/copy_icon' 400 ()
So it isn't trying to get it from templateCache. Is there a way to do this?
Update
I tried ...
$http.get('://www.drupal.org/files/issues/sample_7.png').success(function (t) {
$templateCache.put('img/help/copy_icon', t);
});
But that didn't work either

I do not know exactly what you try to achieve by using $templateCache, which in your case just saves image URL to the cache, but I modified your code a bit, so it displays an image, I added controller:
app.run(function($templateCache){
$templateCache.put('img/help/copy_icon', 'http://www.drupal.org/files/issues/sample_7.png')
})
app.directive('ngImg', function(){
return {
rectrict: "E",
scope: {
url: "#url"
},
template: '<img ng-src="{{ imgUrl }}">',
controller: function ($scope, $templateCache) {
$scope.imgUrl = $templateCache.get($scope.url);
}
}
})
plunker: https://plnkr.co/edit/q5a9ptq8rd1G4uGkkNMe?p=preview
BTW, using ng prefix for custom directives names is not recommended and should be reserved for angular core directives/components

Related

how to change the angularjs custom directive templateUrl dynamically with using scope

This is my first question so I hope I can explain the situation
The angularJs documentation here talks about having the directive templateUrl as a function to be returned dynamically. There is also a Plunkler live demo here.
.directive('....', function() {
return {
templateUrl: function(elem, attr){
return **.... scope.Somthing ...**;
}
};
});
the function does not take a scope parameter and this is the main issue
The only way so far that i found is to set the TemplateUrl dynamically with relevance to the directive scope is this way
.directive('....', function() {
return {
link: function (scope, element, attrs) {
scope.getTemplateUrl = function () {
return **.... scope.Somthing ...**;
};
},
template: '<ng-include src="getTemplateUrl()"/>'
};
});
another solution is
.directive('....', function() {
return {
controller: function ($scope) {
$scope.getTemplateUrl = function () {
return **.... scope.Somthing ...**;
};
},
template: '<ng-include src="getTemplateUrl()"/>'
};
});
my first issue is that this looks like patch to the problem
my second issue is having to build html string in the directive.
Is there any other way to achive ?
Lets split your problem for 2 problems :D
First problem is about storing template in js.
This problem can be solved using the $templateCache and injecting
<script id="myTemplate.html" type="text/ng-template"> <div> SOME MARKUP <div> </script>
Here you can read more about this
Second problem is about dynamic templating.
So there is 2 solutions (as far as i know :D)
First solution you have already mentioned - using ng-include.
Second solution is to use $compile to dynamicly compile html with angular directives.
First solution is little bit better, because in the second case you have to always remember about memory leak. Look here for more info and here

Highlights don't work in external template

I am a noob with angularjs and I have a problem.
I am using prism.js or highlights.js in my web (same result). It works correctly into index.html but It doesn't work in other templates that I load with ngRoute.
I believe that the problem is angularjs only it renders one more time the html and it doesn't work when I load my content-principal.html.
INDEX.HTML
//<pre><code class="language-javascript">
colour syntax is ok
//</code></pre>
APP.JS
ionicEsApp.config(function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'templates/content-principal.html',
//controller: 'IonicEsController'
}).
content-principal.html
//<pre><code class="language-javascript">
colour syntax is NO work
//</code></pre>
¿any solution? Thanks and sorry by my english :P.
SOLVED.
We need:
index.html
prims.js and prism.css from http://prismjs.com/#basic-usage
app.js
To create a new directive (VERY IMPORTANT before from .conf)
var ionicEsApp = angular.module('ionicEsApp', [
'ngRoute',
'ngResource',
'ionicEsController'
]);
ionicEsApp.directive('ngPrism', [function() {
return {
restrict: 'A',
link: function($scope, element, attrs) {
element.ready(function() {
Prism.highlightElement(element[0]);
});
}
}
}]);
ionicEsApp.config(function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'templates/content-principal.html',
//controller: 'IonicEsController'
}).
otherwise({
redirectTo: '/'
});
});
content-principal.html
We have to use the new directive into code tag.
<pre><code ng-prism class="language-javascript">
alert("Prims is ok");
</code></pre>
NOTE: There is a problem with html, we need replace the < symbol by &lt. Example:
<pre><code class="language-markup">
&lth1> Hello! &lt/h1>
</code></pre>
Can't comment on an answer yet, but I found this technique useful.
If you load your templates 'manually' and insert the text into the dom, Angular will automagically convert the content to HTML entities, meaning your raw template are still readable, but display correctly.
In my application I use $sce and $templateRequest to get the template, then set an angular template variable to the value of the fetched template.
A couple of notes:
I have multiple code samples per directive instance, identified by a codeType variable
My templates filenames are in the form of _{codeType}.sample e.g. _css.sample
The template location is passed in as an attribute of the directive in the dom
The dom element containers are identified by class .sample-{codeType} e.g .sample-css
The angular placeholder is identified by {{sample{codeType}} e.g. {{samplecss}}
To prevent race conditions, I use $timeout to wait a beat and allow the current $apply() to complete before calling Prism on the code.
This method also allows for multiple types of code with similar outputs - for example, in my styleguide I show both the output HTML (codeType = 'html') and the un-rendered Angular templates (codeType = 'ng') - both require the Prism .language-markup class.
This can be simplified a lot if you only have one code sample per directive.
function StyleGuideComponentController($scope, $element, $templateRequest, $sce, $timeout)
{
var codeSampleTypes =
[
'html',
'ng',
'ngjs',
'css',
'less'
];
insertAllCodeSamples();
function insertAllCodeSamples()
{
var key;
for (key in codeSampleTypes)
{
insertCodeSample(codeSampleTypes[key]);
}
}
function insertCodeSample(codeType)
{
var sampleUrl = $scope.templateLocation + '/_' + codeType + '.sample',
sampleCode = $sce.getTrustedResourceUrl(sampleUrl);
$templateRequest(sampleCode).then(function(template)
{
var codeElement = $element.find('.sample-' + codeType)[0],
prismLanguage = codeType,
prismLanguageTypes =
{
'html' : 'markup',
'ng' : 'markup',
'js' : 'javascript',
'ngjs' : 'javascript'
},
key;
for (key in prismLanguageTypes)
{
if (prismLanguage === key)
{
prismLanguage = prismLanguageTypes[key];
}
}
codeElement.className += ' language-' + prismLanguage;
$scope['sample' + codeType] = template;
$timeout(function()
{
Prism.highlightElement(codeElement);
});
}, function()
{
$scope['sample' + codeType] = 'An error occurred' +
' while fetching the code sample';
});
}
return {
restrict : 'E',
scope :
{
templateLocation: '='
},
controller : StyleGuideComponentController
};
}
There is a really easy way to do this if you are using ng-view to load the template:
if you have something like this:
<div ng-controller="MainCtrl">
<div id="content" ng-view>
</div>
</div>
You can add this to your MainCtrl controller:
$scope.$on('$viewContentLoaded', function(){
Prism.highlightAll();
});
Now, if you use the default way to highlight the code:
<pre><code class="language-javascript">
Prism will highlight it
</code></pre>
Prism will highlight it!

Execution flow of a directive in angular js and using its attributes

hello i would like to know the steps of execution of directives and some fundamental details about how the processing happens this would be very helpful for more customization of directives and exploit its features...
i have a sample template with a directive and the attributes needed and few html tags as shown
template1:-
<directive1 s-web-service-path="object.WebServicePath" >
<h1>any html content</h1>
</directive1>
my directive is i.e. it calls a web service to get its content
widgetsModule.directive("directive1", function ($http) {
try {
return {
restrict: "E",
replace: true,
transclude: true,
scope: {
sWebServicePath: "="
},
template: '<div ng-transclude><h1>My content {{result }}</h1> </div> ',
link: function (scope, element, attrs) {
var request = '<request struct>';
$http({ method: "POST", url: scope.sWebServicePath, data: request }).
success(function (data, status) {
scope.result = data;
}).
error(function (data, status) {
alert("Service Call Error");
})
}
}
}
catch (e) {
alert(e);
}
});
What is the difference between attrs and $scope in the link function... in above case
$scope.sWebServicePath gives me the value of object.WebServicePath i.e. something like "http://anypath.asmx"
but
attrs.sWebServicePath give me object.WebServicePath... why is this difference and how is it useful?
I know that putting "ng-transclude" would enable me to have
<h1>any html content</h1>
in the specified div of my template with in the directive but how does the execution happens?
and why is that return is to be written in a directive it returns a link function alright and it can be used for DOM manipulation but any example of when do i use it?
i know these might sound very fundamental but please do throw some light on the execution flow of the directive...or some good source of reference...thank you! and advice/tips on the usage of the parameters of the directive would be very helpful
this link has the best documentation on usage of directives they should have put this link under directive definition ... js came across this page while reading the angular documentation
http://docs.angularjs.org/api/ng.$compile
if you use http request in directive you dont forget for $watch because http calls are asynchronous.
Diference between attr and scope is:
scope - is own scope of directive
attr - are attribs of directive
i think so data passed through attr not have to always same as your own scope, because you can make your new own scope for directive but cant change attr.
may be helpful for you
about-those-directives
egghead.io
onehungrymind.com/angularjs-directives-basics/
2013 - angularjs-directives-using-isolated-scope-with-attributes
many sources
AngularJS-Learning

Writing an angular directive with asynchronous data

I'm writing a small app that uses the Instagram API. I'm trying to write a directive to display a list of the logged in users images. I have a back end api that calls the Instagram API and returns the results.
.directive('userPhotos', function($http)
{
return {
restrict: 'E',
template: '<ul class="user-photos">'
+'<li ng-repeat="image in images">'
+'<img src="{{image.images.low_resolution.url}}">'
+'</li>'
+'</ul>',
replace: true,
controller: function($scope, $element, $attrs){
$scope.images;
$scope.serviceURL = "/api/photos/"+$attrs.photosPerLoad;
$scope.loadPhotos = function()
{
$http.get(this.serviceURL)
.success(function(response){
$scope.images = response.data;
})
.error(function(response){
// show error
});
}
},
link: function($scope, element, attribute){
$scope.loadPhotos();
}
}
})
This works in that it displays the images as desired once the result of the API call is complete. However, as I have defined a src attribute for the img tag in the template during the initial phase of the Angular process this is called and I get the following.
GET http://myapp.dev/%7B%7Bimage.images.low_resolution.url%7D%7D 500 (Internal Server Error)
I'm still a bit vague on the process Angular goes through as it's putting a directive together but I think I understand that initially, for the ng-repeat region there is a copy of the contents of this region made to be filled once the images binding is populated.
Anyhow, can anyone advise how I could get around this?
So to clarify... this was solved by changing the template part of the directive to...
template: '<ul class="user-photos">'
+'<li ng-repeat="image in images">'
+'<img ng-src="{{image.images.low_resolution.url}}">'
+'</li>'
+'</ul>',
Thanks! #madhead.

Issue in creating custom directives of marquee of images (using Angular)

I am trying to move marquee of images to a custom directive. Initially in my index file i had a div like below
<div id="marquePic" style="width:90%"></div>
and later in the script(end of body) I was doing something like below
$(document).ready(function(){
var picData = [ //image data(json),param:image(image path),title(image title),link(image link)
{
image:'http://wowslider.com/sliders/demo-33/data1/images/dahlia.jpg',
title:'bbb',
link:'#'
},
{
image:'http://wowslider.com/sliders/demo-33/data1/images/dahlia.jpg',
title:'aa',
link:'#'
}
];
$("#marquePic").picMarque({
speed: 60,//scroll speed(ms)
errorimg: 'http://www.siaa.org.cn/style/common/nophoto.jpg',//error image path
data: picData
});
});
I am using jQuery PicMarquee.js to get marquee of images.
Doing above i was able to create marquee if images..Later i thought of using angular and move my html code to a separate directive so that i can reuse it.(Please note: For simplicity only I have only one div with marquee as id.In reality there are few more html elements and hence thought of creating custom directive)
When I create a custom directive above code doesn't work
<our-clients></our-clients>
and in js i have
ourApp.directive('ourClients', function() {
return {
replace: true,
templateUrl: 'directives/clients.html'
};
});
clients.html has only data related to marquee eg
<div id="marquePic" style="width:90%"></div>
and marquee related js(picData etc) is in the original html file which includes my custom directive.
However, after doing above i don't see it working. Please suggest.
Provide your profile pictures array to your directive and let it process those and call your third party library.
Also I'd not use id for that if you want to make a directive for it.
Controller:
$scope.picData = [{... images here ...}, {...}]
In Directive:
ourApp.directive('ourClients', function() {
return {
replace: true,
templateUrl: 'directives/clients.html',
scope: {
images: '='
}
link: function($scope, element){
//or just use $(element).picMargue
$(element).find('.marquePic').picMarque({
speed: 60,//scroll speed(ms)
errorimg: 'http://www.siaa.org.cn/style/common/nophoto.jpg',//error image path
data: $scope.images
});
}
};
});
Directive html:
<div>
<div class="marquePic"></div>
</div>
Call it:
<our-clients images="picData"></our-clients>

Resources