binding an expression into ng-src directive - angularjs

i am trying to load google map api link inside ng-src directive using this method..
<script ng-src="{{trustSrc(vCustom.googleMapApi.src)}}"></script>
in my controller i have..
v.googleMapApi = { src: "https://maps.googleapis.com/maps/api/js?key=" + config.googleApiKey + "&libraries=places" };
$scope.trustSrc = function (src) {
return $sce.trustAsResourceUrl(src);
}
sometimes it works and some times it doesn't..
The Error
ReferenceError: google is not defined...
i have tried different ways to bind it inside ng-src directive but no success..
it works when i add this script <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"></script> but it doesn't work dynamically.. any help ??
there is no syntax error and my controller is ng-controller="Custom as vCustom"
any suggestions to bind it in ng-src directive ?

I think you are trying to lazy load the script. Pls have a look at below post it may help. How to asyncronously load a google map in AngularJS?

Let me try to explain the scenario as best as I can :)
The <script> tags are evaluated only once in a web application. Unlike img tags which can have src attribute assigned to different values throughout the app and so are re-evaluated. So what's happening is that sometimes when the compiler gets to your script tag, the model (vCustom.googleMapApi.src) is resolved so it works fine but sometimes it doesn't because the $digest loop (events loop) in angular hasn't finished resolving the model and so the API key isn't passed correctly to script tag which results in not loading the google maps API and then where you're using the map, it throws the error. In that case, to verify, check the script tag on chrome debugger, it won't have the correct API key resolved and the api script won't have been loaded.
Now the question is that what's the solution. You can either implement a directive that initially resolves the APIKey model and then appends the script tag into your HTML, or use the hard coded value as you use it right now (i have usually seen it hardcoded in most of the code and examples i've seen).
NOTE: even if you implement such directive, you have to make sure that you are using the google maps api AFTER your directive has executed and you've got the maps api loaded.
Hope this helps.

Related

HTML and JAVASCRIPT Editor in Angularjs

I have an angularjs 1.5.8 application created using Jhipster.
For my website I want to make a HTML and JAVASCRIPT editor. Need to allow user to write HTML Code but JAVASCRIPT also.
Using this library I know I can achieve the follow.
https://github.com/incuna/angular-bind-html-compile
1: Bind HTML Code.
2: Bind Angular code if present in HTML
Eg: <h1>{{$scope.test}}</h1>
Would render correct value in the scope.
But what about something like this in the html
<script>
console.log($scope);
</script>
I get a $scope not defined error, somehow the $scope value is not available in the script tag.
If anyone curious that why I need to do this because we want to provide users of the application to create there own Angularjs Forms.
I solved using ng-include, here is the example source.
I wanted to do two things.
1: Make ng-include work from a scope variable which will contain html and javascript.
2: In the included string if I have a script tag I wanted it to render correct in the ng-include.
To achieve the #1 I did the following.
Used $templateCache service.
Sample code.
$templateCache.put('template-form', vm.html + vm.script);
For point #2
I made sure the script tag is structured in the following way.
<script>
(function() {
'use strict';
angular.module('myApp').controllerProvider.register('AppTemplateController',AppTemplateController);
AppTemplateController.$inject = ['$scope'];
function AppTemplateController($scope){
// WRITE YOUR CODE IN THIS CONTROLLER
// YOU CAN WRITE YOUR VARIABLES/FUNCTIONS HERE.
// MAKE SURE TO CALL THE method "vm.submitForm", to submit your form and pass the form object.
};
})();
</script>
This way you can inject a controller.
My requirement was very very specific to my projecct, I am not sure if others who did not face this issue even would understand what I am talking about. But for those who do face it, I hope you it helpful

Render initial Angular ng-view on server-side and take it from there

I want to avoid the latency in display of initial JavaScript-rendered views. I want the user to see content immediately and have Angular take it from there. I do not want to just replace this ng-view when Angular ngRoute kicks in as a blink will likely happen. I only want it to replace it once the user hits another route.
Let's imagine this is the base route '/'. This would already exist in my HTML, rendered from the server.
<div ng-view>
<h1>Welcome. I am the first view.</h1>
<p>Please do not replace me until a user has triggered another route.</p>
</div>
I know that a common approach is to have some server-side code in an ng-view and when Angular loads it just replaces it. This is not what I'm looking to do. I want Angular to load and understand that this is actually already my first view.
Any creative ideas as to how to do this? I've looked at the source code- no luck. Maybe even a way to have Angular only replace the HTML if it is different.
Edit:
I am not looking to render templates on the server-side for use as Angular templates. I am looking to render my entire index.html on the server-side, and that would already contain everything the user needs to see for this initial base route.
6-10 seconds on any mobile is quite bad. I wouldn't blame angular here, angular is only 30kb, if that is still too slow, you've chosen wrong framework for task.
Use profiling tools to understand what is going on.
How big is the application you're dealing with?
Can you split the application into sub-applications?
Are you doing minification already for CSS & JS?
Are you lazy loading all your views & controllers?
Are you compressing everything? (gzip)
Anyways, it is possible to do pre-processing on server-side for your index.html
You can do pre-processing using nodejs, for example, and cache the pre-processed index.html.
Your nodejs pre-processor could do (pseudo-code):
function preprocessIndexHtml(queryString) {
if(cached[queryString])) return cached[queryString];
// assume angular.js is loaded
// routeConfiguration is an object that holds controller & url.
var routeConfiguration = $routeProvider.
figureOutRouteConfigurationFor(queryString);
var domTree = $(file('index.html'));
var $rootScope = $injector.get('$rootScope');
// find ng-view and clone it
var yourNgView = $($("attribute[ng-view='']").outerHTML);
// le's get rid of existing ng-view attribute
// and configure new ng-view with templateUrl & controller.
yourNgView.RemoveNgViewAttribute();
yourNgView.AddAttribute("ng-controller", routeConfiguration.controller);
yourNgView.AddAttribute("ng-view", routeConfiguration.templateUrl);
// compile the view & pass the rootScope.
$compile(yourNgView)($rootScope);
// replace the existing dom element with our compiled variant
$("attribute[ng-view='']").replaceHtmlWith(yourNgView);
// we can now cache the resulted html.
return cached[queryString] = domTree.html;
}
ngCloak
The ngCloak directive is used to prevent the Angular html template from being briefly displayed by the browser in its raw (uncompiled) form while your application is loading. Use this directive to avoid the undesirable flicker effect caused by the html template display.
https://docs.angularjs.org/api/ng/directive/ngCloak
<body ng-cloak>
You should read this article http://sc5.io/posts/how-to-implement-loaders-for-an-angularjs-app

Is it possible to know the name of controller which responsible for some HTML fragment from browser?

i'm beginning angular developer and i have application with some controllers.
Is it possible to find out what is the Name the controller of some html if there is no "ng-controller" statement?
Like in case this is custom directive or the html loaded by ui-router?
p.s. i know about batarang but i dont see the name of the controller, only the scope
Thanks
If you can get hold of the DOM element you are interested in, you can run in the console:
angular.element(...).controller().constructor
This will print the constructor function (i.e. the function you have registered as controller) in the console; clicking on it (at least on Firebug) gets you to the source.
.controller() is an addon to the jQuery API from Angular. To get hold of the element in interest, the simplest thing is document.getElementById(). You can even use Firebug (or equivalent) to place an id in that element and then use getElementById().
Also for Firefox/Firebug let me propose the excellent angscope plugin.

browser.executeScript doesn't see $scope

i am making a test with protractor for my angularjs app
and i came accross the following problem
what i want to do is :
browser.executeScript('$scope.$apply')
i want to do this so that my screen updates/renders so i can get the values on screen
only when i do this it says : $scope is not defined
if have also tried multiple javascript render ways who also failed ,but i am not sure if i have used the right methods for that...
does anybody has the same problem or know how to fix this?
Perhaps you should be using an ng-view directive in your container markup to render html snippets or partials within your index page. Take a look at what ng-view can do (http://docs.angularjs.org/api/ngRoute.directive:ngView) :-)

$compile is loading images before the string is even evaluated for Angular expressions

I am building a service to handle modal windows in my Angular application, so there is a bit of manual work with linking a template, scope and controller.
I'm using $compile like so, to build the template and attach to the scope, for example:
$compile('<h1>This is my window</h1><img src="{{ imageUrl }}">')($scope);
Everything is working fine, but... the browser tries to load anything such as an image before the HTML string has even been evaluated for Angular expressions. For example, in this case, the browser tries to literally load "http://myhost.com/{{ imageUrl }}", and then immediately afterwards will load the correct URL as the Angular expression is picked up.
This happens immediately upon the $compile()($scope) is called, without even attaching/inserting the returned template to the DOM.
Basically the browser seems to be parsing the HTML before Angular replaces the Angular expressions - any kind of remote content in the HTML at all will be requested by the browser. How is this so?
Use ng-src instead of src. That's what it's for.
You need to use ng-src in the img tag.

Resources