Google maps for AngularJS - angularjs

I am very new to AngularJS and I am trying to use https://github.com/angular-ui/angular-google-maps.
I am just trying to get the map to render on my page but I am getting an error message and I don't know what it means. Any help with understanding this error message would be appreciated.
I've created a plunk here:
github.com/twdean/plunk
Here is the Error in the browser:
Error: [$compile:multidir] Multiple directives [googleMap, markers] asking for new/isolated scope on: <google-map center="center" draggable="true" zoom="zoom" markers="markers" mark-click="true" style="height: 400px">
http://errors.angularjs.org/1.2.3/$compile/multidir?p0=googleMap&p1=markers&p2=new%2Fisolated%20scope&p3=%3Cgoogle-map%20center%3D%22center%22%20draggable%3D%22true%22%20zoom%3D%2

I suggest another alternative, ng-map.
I created a google maps angularjs directive called, ng-map, for my own project. This does not require any Javascript coding for simple functionality.
To Get Started
One. Download and include ng-map.js or ng-map.min.js
<script src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script src="dist/ng-map.min.js"></script>`
Two. use map tag, and optionally, control, marker, and shape tags
<ng-map zoom="11" center="[40.74, -74.18]">
<marker position="[40.74, -74.18]" />
<shape name="circle" radius="400" center="[40.74,-74.18]" radius="4000" />
<control name="overviewMap" opened="true" />
</ng-map>`
Examples
To use it in your app, simply include 'ngMap' as dependency to your app.
var myApp = angular.module('myApp', ['ngMap']);
Hope it helps
-------------- EDIT -------------------
For those who looks for angular2 version,
there is also ng2-map https://ng2-ui.github.io/#/google-map

It seems that you're including a "markers" attribute within your google-map element.
Indeed as #Tyler Eich mentions, the docs as of Dec 5, 2013 remain outdated. Removing the marker attribute seems to make it work.
Here is how to display markers:
index.html
<div ng-controller="MapCtrl">
<google-map id="mymap"
center="center"
zoom="zoom"
draggable="true"
mark-click="false">
<markers>
<marker ng-repeat="marker in markers" coords="marker">
</marker>
</markers>
</google-map>
</div>
controller.js
var controller = module.controller('MapCtrl', function($scope) {
$scope.myMarkers = [
{
"latitude":33.22,
"longitude":35.33
},
...
];
$scope.center = {
latitude: 33.895497,
longitude: 35.480347,
};
$scope.zoom = 13;
$scope.markers = $scope.myMarkers;
$scope.fit = true;
});

I have just today had a need to implement a google map into my angular application. Since my implementation required something quite simple I decided to do this myself and create a simple directive. I will leave my source below for anyone who might find it usefull.
Create a directive
Create HTML
Optionally pass the coordinates through directive/controller if
you need.
DIRECTIVE
angular.module('ngPortalApp')
.directive('googleMap', function () {
return {
template: '<iframe width="100%" height="350" frameborder="0" style="border:0"></iframe>',
restrict: 'E',
scope: {
pbcode: '='
},
link: function postLink(scope, element) {
var mapFrame = element.find("iframe");
if (scope.pbcode) {
mapFrame.attr('src', "https://www.google.com/maps/embed?pb=" + scope.pbcode);
}
else {
mapFrame.attr('src', '');
}
}
};
});
HTML
<div class="col-lg-12">
<google-map pbcode="'!1m0!3m2!1sen!2srs!4v1445332712674!6m8!1m7!1s34JkuBgIzmIJNmpFNThuUg!2m2!1d40.75816449978445!2d-73.98911289129973!3f175.51693470959802!4f7.069842517148402!5f0.7820865974627469'"></google-map>
</div>
Thats all there is to it. Remember that the google query string is called "pb" this is the code used in all embed codes you can grab from google. You may pass this to your directive straight up or if you need to via your controller or even through the directive itself. You can set any iframe map settings in the directive within the template.
To change between Street View or Map View you just send the corresponding code whichever source you are getting them from (db, json, etc).
For the above example:
Street Code:
!1m0!3m2!1sen!2srs!4v1445332712674!6m8!1m7!1s34JkuBgIzmIJNmpFNThuUg!2m2!1d40.75816449978445!2d-73.98911289129973!3f175.51693470959802!4f7.069842517148402!5f0.7820865974627469
Map Code:
!1m18!1m12!1m3!1d755.5452773113641!2d-73.98946157079955!3d40.75804119870795!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0000000000000000%3A0x1952a6258d36ecc5!2sMcDonald's!5e0!3m2!1sen!2srs!4v1445332854795
Haven't had any issues with this as yet.
Here's a fiddle: jsFiddle

If you want to include markers you should do that in another element inside the google-maps directive.
You should do something like:
<google-maps options="someOptionsObject">
<markers cords="someArrayWithLatitudeAndLongitudeCords"></markers>
</google-maps>

For Angular2, there is angular2-google-maps. License as of 2016-05-14: MIT.

Related

How to hide <img> using md-switch

angular-material newbie here. I'm trying to hide some elements in our site using a switch, as instructed by our client. This led me to angular-material's md-switch.
So I tried incorporating it like so...
<md-switch md-no-ink aria-label="switchView" ng-model="switchView">{{switchView}}</md-switch>
And called the value of the switch in my element like this:
<img ng-src="{{photoPath}}" class="profilePic" ng-hide="switchView"/>
After testing it though, it didn't hide my <img> even though my switchView changed its value. Am I missing something here?
Other methods I've tried:
Adding ng-change to my md-switch, which called a function that would equate another variable (e.g. $scope.toggleView = $scope.switchView) with switchView's value. $scope.toggleView would then be used in my ng-hide.
ng-hide = "switchView == true".
Any advice would be very much appreciated. Thank you.
UPDATE 1: To test it, I tried hiding the <div> beside my <md-switch> and it worked perfectly. However it's still not working with my <img>.
Further checking revealed that it was inside a <nav> element. However they're both using the same controller. I wonder if that's the problem? I assumed that it shouldn't be a problem because of this.
The structure is like this:
<nav ng-controller="MainController">
<!-- other navigation elements here -->
<img ng-src="{{photoPath}}" class="profilePic" ng-hide="switchView"/>
</nav>
<div ng-controller="MainController">
<div>Toggle Switch</div>
<md-switch md-no-ink aria-label="switchView" ng-model="switchView">{{switchView}}</md-switch>
</div>
UPDATE 2: I've added the following code in my JS file because there are plans to hide elements in other pages. It still didn't work.
$scope.onChange = function(value) {
$scope.$broadcast("view_mode", $scope.switchView);
}
$scope.$on("view_mode", function(event, switchValue) {
$scope.viewThis= switchValue;
});
My HTML now looks like this:
<img ng-src="{{photoPath}}" class="profilePic" ng-hide="viewThis"/>
As for the controller, ngMaterial was called in a separate JS file (our main), together with all our dependencies and configs. Hence, this wasn't called inside MainController.
mainApp.js
var app = angular.module('myAppModule', [
// other references here
'ngMaterial'
]);
mySample.js
angular
.module('myAppModule')
.controller('MainController', ['$scope', function ($scope) {
// functions etc. go here
Hope this helps clear things up. Thank you.
Try something like this, its a trivial example but hope it helps. Here's a link to working codepen.
There seems to be a couple ways you could handle this according to the docs:
Angular Material- MD-Switch
function exampleController($scope) {
$scope.secondModel = false;
$scope.onChangeEvent = function(value) {
$scope.imgSource = (value) ? 'http://www.fillmurray.com/300/200' : 'http://www.fillmurray.com/g/155/300';
};
// alternatively: you could set the ternary to empty string value here.
}
angular
.module('BlankApp', ['ngMaterial'])
.controller('exampleController', exampleController);
<md-switch ng-model="switchValue" ng-change="onChangeEvent(switchValue)">
<img ng-src="{{imgSource}}" alt="" />
</md-switch>
<md-switch ng-model="secondModel">
<img src="http://www.fillmurray.com/300/200" alt="" ng-hide="secondModel" />
</md-switch>
Thank you to everyone who gave their inputs. After some research, I managed to solve this problem using factories (source).
I'm sharing my solution so that it may help others who experience the same problem.
HTML:
<nav ng-controller="MainController">
<!-- other navigation elements here -->
<img ng-src="{{photoPath}}" class="profilePic" ng-hide="switchView"/>
</nav>
<div ng-controller="MainController">
<div>Toggle Switch</div>
<md-switch md-no-ink aria-label="switchView" ng-model="switchView" ng-change="onChange(switchView)">{{switchView}}</md-switch>
</div>
JS:
angular
.module('myAppModule')
.controller('MainController', ['$scope', 'ViewModeFactory', function ($scope, ViewModeFactory) {
// functions etc. go here
// For client presentation mode
$scope.onChange = function(value) {
ViewModeFactory.setViewMode($scope.switchView);
}
$scope.$watch(function (){
$scope.switchView = ViewModeFactory.getViewMode();
});
}])
.factory('ViewModeFactory', function () {
var data = {isViewMode: ''};
return {
getViewMode: function () {
return data.isViewMode;
},
setViewMode: function(value) {
data.isViewMode = value;
}
};
});
I used factories so that other controllers in our site can use the value passed by md-switch.
Hope this helps.

Is it possible to access JSP style tag values in an angularjs html view?

Is it possible to access JSP style tag values in an angularjs html view? For example, can I get the ‘principal.firstName’ value in the browser, from the tag below? Is there an Angularjs way to do this?
<sec:authentication property="principal.firstName"/>
… or, do I need to access this serverside, and return in JSON? If I do need to access it server side, could you point me to an example, everything I have found just shows how to get principal.getName().
I’m trying to convert our jsp pages to be html.
I was able to do essentially the same thing by creating a JSON object, the values of which were these JSP variables which would be filled in by the server. This JSON object can be a separate page that is accessed by Angular using an $http.get() function.
Like this:
{'mySettings': {
'userID': <%=user.ID%>,
'firstName': '<%=user.first_name%>',
'lastName': '<%=user.last_name%>'
}}
The server will process the <%=whatever%> directives and replace them with actual data. Then your AngularJS code will issue an http.get to pull in this JSON and use it on the client.
You can create directive, that will read your attribute from sec:authentication tag and pass it on variable.
Example on jsfiddle.
angular.module('ExampleApp', [])
.controller('ExampleController', function() {
this.firstName = 1;
})
.directive("myProperty", function() {
return {
scope: {
val: "=myProperty"
},
link: function(scope, elem, attr) {
scope.val = attr.property;
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="ExampleApp">
<div ng-controller="ExampleController as vm">
<sec:authentication my-property="vm.firstName" property="principal.firstName" />{{vm.firstName}}
<div my-property="vm.name" property="john doe"></div>{{vm.name}}
</div>
</div>

Using KendoUI methods in AngularJS

How can I use the methods provided by KendoUI widgets in an AngularJS application?
For the configuration of the widgets the directive attributes are used within the markup via k- prefixes, I know.
But in the documentation, there are a lot of methods assigned to the widgets.
For example the kendo-mobile-tab-strip widget has a switchTo method.
The example shows to use it this way (without angular)
var app = new kendo.mobile.Application();
function onClick() {
var tabstrip = app.view().footer.find(".km-tabstrip").data("kendoMobileTabStrip");
tabstrip.switchTo("#bar"); //activate "bar" tab
}
How can I access the app variable in an Angular controller, when I just use a <kendo-mobile-application> directive to initialize the app?
Is there any other (proper) way of using the widget methods?
I'm curious of the best practice here, because this all feels not like Angular...
When you supply a value to the widget's attribute (or to a k-scope-field attribute), that becomes the name of the scope property which you can use to get a reference to the widget.
HTML
<div ng-controller="MainCtrl">
<div kendo-grid="myGrid"></div>
<!-- or -->
<div kendo-grid k-scope-field="myGrid"></div>
</div>
Controller
angular.controller("MainCtrl", function($scope) {
// the widget is accessible from the scope
$scope.myGrid.doSomething();
});
You're right, calling methods on widget isn't like Angular. So in most cases you want to be putting this in your own directives, wrapping kendo's widgets. This lets you keep DOM specific code out of your application controllers and contained in directives, where they belong.
HTML
<div ng-controller="MainCtrl">
<my-grid-directive></my-grid-directive>
</div>
Directive
angular.controller("myGridDirective", function() {
return {
template: "<div kendo-grid='myGrid'></div>",
link: function (scope, element, attrs) {
scope.myGrid.doSomething();
}
};
});
I never using kendo mobile application so it might be different but in general to access the kendo object in the $scope object by adding identifier in kendo attribute per example below.
<div ng-app="app" ng-controller="MyCtrl">
<input kendo-datepicker="datePicker" k-on-change="onChange()">
</div>
<script>
angular.module("app", [ "kendo.directives" ]).controller("MyCtrl", function($scope) {
$scope.onChange = function() {
alert($scope.datePicker.value());
};
});
</script>
http://docs.telerik.com/kendo-ui/AngularJS/introduction#getting-widget-references

TooltipHtmlUnsafe with content fetched from another div

I'm trying to show a tooltip with html content and the html I would like to be fetched from a children div which has angular markup in it.
Before I switched to ui-bootstrap I used the default bootstrap tooltip, which I created in a directive filling the content with ('.my-tooltip-content',element).html()
Now with ui-bootstrap I tried using the same directive/logic on the ui-tooltip except that now I tried setting attribute variables. The problem is, that I don't know how to get the html from my .my-tooltip-content div rendered inside the tooltip, without loosing the bindings. If I use $interpolate, I get the html of my div properly rendered, but the output is fixed then of course (doesn't update anymore), $compile I have never used before, but I thought this would be the right place for such a use, maybe I don't know how to use it, but $compile gives me an exception about circular structure.
This is a shortened version of what my app looks like:
http://plnkr.co/edit/46NsEPArtm4hph0ROlPS?p=preview
Excerpt:
<div class="hover" tooltip-html-unsafe="" tooltip-trigger="mouseenter" tooltip-placement="bottom">
<div>
<p>Hover me {{booking.name}} !</p>
<!-- about 20 more lines -->
</div>
<div class="my-tooltip-content"><!-- hidden by default -->
<p class="booker-name">{{booking.name}}</p>
<p>Does the name in this tooltip update?</p>
<!-- about 10 more complex lines -->
</div>
</div>
anApp.directive('hover', ['$compile','$interpolate', function($compile,$interpolate){
return{
restrict: 'C',
link: function(scope,element,attrs){
var html1,html2,html3;
var content = $(element).find('.my-tooltip-content');
// This works, but no binding
html1 = $interpolate(content.html())(scope);
// This I'd like to work, but I get "Can't interpolate: {{tt_content}} TypeError: Converting circular structure to JSON"
html2 = $compile(content.html())(scope);
// This brings my html into the tooltip but curlybraces are curlybraces (not compiled)
html3 = content.html();
attrs.tooltipHtmlUnsafe = html1;
}
}
}])
Is there an easy way to to get the html of .my-tooltip-content with all it's angular markup/bindings injected into the tooltip-content variable ?
PS: I know that I could squeeze all the html just directly into the tooltip-html-unsafe attribute, but I have so many lines in my real-world my-tooltip-content that this just wouldn't work (would make the tooltip-content html unreadable and unchangeable for humans).
If you need to use a child div, one solution use a function to pass the interpolated contents of the div to the tooltip. For example:
anApp.directive('hover', ['$compile','$interpolate', function($compile,$interpolate){
return{
restrict: 'C',
link: function(scope,element,attrs){
scope.myTooltip = function() {
var content = $(element).find('.tooltip-content');
return $interpolate(content.html())(scope);
};
}
}
}])
And your html would would need to be updated to use the new scope value for the tooltip:
<div class="hover" tooltip-html-unsafe="{{myTooltip()}}" tooltip-trigger="mouseenter" tooltip-placement="bottom">
Here's the updated plnkr

Can I use one ng-app inside another one in AngularJS

I have two ng-app
like ;
<div ng-app="app1" >
somexpression
<div ng-app="app2">
some more expression
</div>
</div>
is there any way to make it work?
when I make a nested ng-app it doesn't work
I know that I can use two different controller but I don't want to use two controllers
---- EDIT -----
The thing is;
angular.module('AppName', [
'angular-carousel'
])
SO I need somehow to change this ng-app to directive
From the AngularJS document, the answer is no
http://docs.angularjs.org/api/ng/directive/ngApp
AngularJS applications cannot be nested within each other.
And if not nested, then it's OK, someone already asked this question, refer here:AngularJS Multiple ng-app within a page
and the AnguarJS document
http://docs.angularjs.org/api/ng/directive/ngApp
Only one AngularJS application can be auto-bootstrapped per HTML document. The first ngApp found in the document will be used to define the root element to auto-bootstrap as an application. To run multiple applications in an HTML document you must manually bootstrap them using angular.bootstrap instead.
I found one tricky solution for this problem. The idea is that the "host" application have to somehow jump over the root element of nested application. I used directive for this:
angular.module("ng").directive("ngIsolateApp", function() {
return {
"scope" : {},
"restrict" : "AEC",
"compile" : function(element, attrs) {
// removing body
var html = element.html();
element.html('');
return function(scope, element) {
// destroy scope
scope.$destroy();
// async
setTimeout(function() {
// prepare root element for new app
var newRoot = document.createElement("div");
newRoot.innerHTML = html;
// bootstrap module
angular.bootstrap(newRoot, [attrs["ngIsolateApp"]]);
// add it to page
element.append(newRoot);
});
}
}
}
});
Example simple app:
// module definition
angular.module("testMod1",[])
.service("moduleService", function ModuleService() {
this.counter = 0;
this.getCounter = function() {
return this.counter;
};
this.incCounter = function() {
this.counter += 1;
}
})
.controller("ModuleCtrl", function(moduleService) {
this.getValue = function() {
return moduleService.getCounter();
};
this.incValue = function() {
moduleService.incCounter();
};
});
Now in the markup we can use the ng-isolate-app:
<!-- App instance 1 -->
<body ng-app="testMod1">
<div ng-controller="ModuleCtrl as ctrl">
{{ctrl.getValue()}}
<button ng-click="ctrl.incValue()">Click</button>
<!-- App instance 2 -->
<div ng-isolate-app="testMod1">
<div ng-controller="ModuleCtrl as ctrl">
{{ctrl.getValue()}}
<button ng-click="ctrl.incValue()">Click</button>
<!-- App instance 3 -->
<div ng-isolate-app="testMod1">
<div ng-controller="ModuleCtrl as ctrl">
{{ctrl.getValue()}}
<button ng-click="ctrl.incValue()">Click</button>
</div>
</div>
</div>
</div>
</div>
</body>
Working example on plnkr
This works in simple cases, I do not know how this will work on complex applications.
You can't use one ng-app inside another one in angularjs.
because AngularJS applications cannot be nested within each other.
https://docs.angularjs.org/api/ng/directive/ngApp

Resources