I'm trying to move a marker inside the google maps map. I have a function to move them and they are working fine. For testing, I had invoked them inside the script and they are working as expected.
But when I am trying to call the function within the ng-click directive, the function is getting called but the entire code is not being executed.
<md-button class="md-raised md-primary" ng-click="x()">Click here to move the marker</md-button>
Method:
$scope.x = function ()
{
console.log('a');
$scope.marker = {
id: 6,
coords: {latitude:-28.226349,longitude:-52.381581}
};
}
Inside the console the 'a' is getting printed, but the marker doesn't move to latitude: -28.226349, longitude: -52.381581.
If I call the function inside the script like this:
$scope.x = function ()
{
console.log('a');
$scope.marker = {
id: 6,
coords: {latitude:-28.226349,longitude:-52.381581}
};
}
$scope.x();
When the page is loaded, the marker is at latitude: -28.226349, longitude: -52.381581.
Entire HTML:
<md-button class="md-raised md-primary" ng-click="x()">Click here to move the marker</md-button>
<div id="map" ng-controller="MapCtrl">
<ui-gmap-google-map center='map.center' zoom='map.zoom' options="map.options">
<ui-gmap-marker coords="marker.coords" options="marker.options" events="marker.events" idkey="6"></ui-gmap-marker>
</ui-gmap-google-map>
Take a look at this codepen here.
It is working as expected. I think the issue is with your idkey. Make the idkey dynamic and bind it to the ID of the marker object.
HTML
<div ng-app="myApp" ng-controller="gMap">
<md-button class="md-raised md-primary" ng-click="x()">Marker</md-button>
<ui-gmap-google-map
center='map.center'
zoom='map.zoom' aria-label="Google map">
<ui-gmap-marker
coords="marker.coords" options="marker.options" events="marker.events" idkey="marker.id">
<ui-gmap-window>
<div>{{marker.window.title}}</div>
</ui-gmap-window>
</ui-gmap-marker>
</ui-gmap-google-map>
</div>
Controller
myApp.controller("gMap", function($scope) {
$scope.x = function() {
console.log('a');
$scope.marker = {
id: 6,
"coords": {
"latitude": "40.7903",
"longitude": "-73.9597"
}
}
}
$scope.marker = {
id: 6,
"coords": {
"latitude": "45.5200",
"longitude": "-122.6819"
}
}
$scope.map = {
center: {
latitude: 39.8282,
longitude: -98.5795
},
zoom: 4
};
});
Related
I have used google map using AngularJs which is working fine. However, on clicking any marker infowindow opens but I need to open it by clicking a radio button outside the map, here is the code sample
HTML
<ng-map default-style="true" center="[24.8615, 67.0099]" zoom="11" scroll-wheel="false" zoom-to-inculude-markers="auto">
<info-window id="rider">
<div ng-non-bindable="">
{{vm.store.name}} <br/>
{{vm.store.title}}<br/>
</div>
</info-window>
<marker ng-repeat="(id, store) in vm.stores" id="{{id}}" icon="../assets/images/rider.png"
position="{{store.position}}"
on-click="vm.showStore(event, id)"></marker>
JavaScript/AngularJs
vm.stores = [
{position: [24.8820869, 67.06881520000002], title: 'Bahadrubad'},
{position: [24.8753973, 67.04096709999999], title: 'Mazar e Quaid'},
{position: [24.8758, 67.0230], title: 'Karachi Zoo'},
{position: [24.8532941, 67.01622309999993], title: 'Saddar Town'}
];
NgMap.getMap().then(function (map) {
vm.map = map;
});
vm.showStore = function (e, storeId) {
vm.store = vm.stores[storeId];
vm.map.showInfoWindow('rider', this);
};
Once the radio button list is initialized:
<label data-ng-repeat="store in vm.stores">
<input type="radio" name="storeList" ng-model="store" ng-value="{{store}}" ng-change='vm.showStoreExt({{$index}})' />
{{store.title}}
</label>
you could specify event handler to display info window as shown below:
vm.showStoreExt = function (index) {
vm.store = vm.stores[index];
var marker = vm.map.markers[index];
vm.map.showInfoWindow('rider', marker);
};
Working example
angular.module('mapApp', ['ngMap'])
.controller('mapController', function (NgMap) {
var vm = this;
vm.stores = [
{ position: [24.8820869, 67.06881520000002], title: 'Bahadrubad' },
{ position: [24.8753973, 67.04096709999999], title: 'Mazar e Quaid' },
{ position: [24.8758, 67.0230], title: 'Karachi Zoo' },
{ position: [24.8532941, 67.01622309999993], title: 'Saddar Town' }
];
NgMap.getMap().then(function (map) {
vm.map = map;
});
vm.showStoreExt = function (index) {
vm.store = vm.stores[index];
var marker = vm.map.markers[index];
vm.map.showInfoWindow('rider', marker);
};
vm.showStore = function (e, storeId) {
vm.store = vm.stores[storeId];
vm.map.showInfoWindow('rider', this);
};
});
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script src="https://rawgit.com/allenhwkim/angularjs-google-maps/master/build/scripts/ng-map.js"></script>
<div ng-app="mapApp" ng-controller="mapController as vm">
<label data-ng-repeat="store in vm.stores">
<input type="radio" name="storeList" ng-model="store" ng-value="{{store}}" ng-change='vm.showStoreExt({{$index}})' />
{{store.title}}
</label>
<ng-map default-style="true" center="[24.8615, 67.0099]" zoom="11" scroll-wheel="false" zoom-to-inculude-markers="auto">
<info-window id="rider">
<div ng-non-bindable="">
{{vm.store.name}} <br/> {{vm.store.title}}
<br/>
</div>
</info-window>
<marker ng-repeat="(id, store) in vm.stores" id="{{id}}" position="{{store.position}}" on-click="vm.showStore(event, id)"></marker>
</ng-map>
</div>
I keep getting the following error message: TypeError: $scope.phraseDetail.forEach is not a function each time I try to find matches and replace text in a single item.
The code below works perfect when iterating over multiple items in an object, i.e. when the API output is as follows:
/api/phrases/
[
{
"id": "f40e0e47-6457-463b-a5f9-9dc97bd2d0ce",
"phrase": "Training {{group}} to develop their {{attribute}} by ensuring they are comfortable with {{factor}}"
},
{
"id": "66314a72-07ae-445c-97c0-4f659387bbb2",
"phrase": "Assisting {{person}} in strength and conditioning work to improve {{factor}}"
}
]
However it does not work when there is only a single item being returned, i.e. as follows:
api/phrases/f40e0e47-6457-463b-a5f9-9dc97bd2d0ce/
{
"id": "f40e0e47-6457-463b-a5f9-9dc97bd2d0ce",
"phrase": "Training {{group}} to develop their {{attribute}} by ensuring they are comfortable with {{factor}}"
}
How can I fix this? I have included my code below:
phrase-detail.html (note: bind-html-compile is a directive I nabbed from https://github.com/incuna/angular-bind-html-compile)
<div class="list">
<div class="item item-text-wrap item-line-height" bind-html-compile="phraseDetail.phrase"></div>
</div>
controllers.js
function PhraseDetailCtrl($scope, $stateParams, PhrasesService, FilterService, $ionicLoading, $timeout) {
$ionicLoading.show({
content: 'Loading',
animation: 'fade-in',
showBackdrop: true,
maxWidth: 200,
showDelay: 0
});
$timeout(function () {
$ionicLoading.hide();
$scope.dataLoaded = true;
$scope.phraseId = $stateParams.phraseId;
PhrasesService.getPhrasesDetail($scope.phraseId).then(function(dataResponse) {
$scope.phraseDetail = dataResponse.data;
var replacers = FilterService.getItemFilter();
$scope.phraseDetail.forEach(function(e){
Object.keys(replacers).forEach(function(key){
e['phrase'] = e['phrase'].replace(new RegExp(key, 'g'), replacers[key]);
})
})
})
}, 1000)
$scope.$watch('toggle', function(){
$scope.toggleText = $scope.toggle ? 'Toggle!' : 'some text';
})
}
services.js
/**
*
*/
function PhrasesService($http) {
this.getPhrasesDetail = function (phraseId) {
return $http({
method: 'GET',
url: server + '/api/phrases/' + phraseId,
});
}
}
/**
*
*/
function FilterService() {
this.getItemFilter = function () {
var replacers = {
'{{group}}' : '<div class="button button-small button-outline button-positive button-side-padding">group</div>',
'{{attribute}}' : '<div class="button button-small button-outline button-assertive button-side-padding">attribute</div>',
'{{factor}}' : '<div class="button button-small button-outline button-assertive button-side-padding">factor</div>',
'{{person}}' : '<div class="button button-small button-outline button-positive button-side-padding">person</div>'
}
return replacers;
}
}
Newbie to Angular Question:
Would like my app to animate all items in an ng-repeat list each time it changes.
Looked over multiple items on this topic including:
AngularJS ng-repeat rerender
http://jimhoskins.com/2012/12/17/angularjs-and-apply.html
Angular.js: Is it possible to re-render ng-repeats based on existing scope data?
Appears I have the same ng-repeat-needs-render-changed-list issue. App works great except animation not being applied to all items in list after the first click.
I have attempted to position $scope.$apply() in code but keeps throwing me ugly errors. Just cannot figure out how/where to apply what I think should be a $scope.$apply().
Relevant HTML here
<!-- Toolbar -->
<md-toolbar class="md-primary">
<div class="md-toolbar-tools">
<span class="product-label"><h1>Car List</h1></span>
</div>
</md-toolbar>
<md-content class="md-padding">
<!--Navigation Bar-->
<md-nav-bar md-selected-nav-item="currentNavItem" nav-bar-aria-label="navigation links">
<md-nav-item md-nav-click="goto('page1')" name="Domestic" ng-click="getType(currentNavItem)">Domestic</md-nav-item>
<md-nav-item md-nav-click="goto('page2')" name="Foreign" ng-click="getType(currentNavItem)">Foreign</md-nav-item>
</md-nav-bar>
<!--run div if nav item has been clicked-->
<div ng-show = "currentNavItem">
<!--flip thru array via ng-repeat and apply animation-->
<div layout="row" layout-wrap>
<div flex="50" class="repeat-animation" ng-repeat="x in carhold2|orderBy track by $index">
<div class="itemcard">
{{x}}
</div>
</div>
</div>
</div>
</md-content>
Javascript here
var app = angular.module('carDash',['ngMaterial', 'ngMessages', 'material.svgAssetsCache', 'ngAnimate'])
.config(configFn);
function configFn($mdThemingProvider) {
$mdThemingProvider.theme('default')
.primaryPalette('blue')
.accentPalette('red');
}
app.controller('AppCtrl', ['$scope', "$http", "$log",
function ($scope, $http, $log) {
//obtain entire json
var g = $http({
url : "car-list.json",
method: 'get'
});
g.success(function (data) {
//populate array based on domestic or foreign selection
$scope.cars = data;
$scope.getType = function (currentNavItem) {
$scope.typo = currentNavItem;
var carhold = [];
for (var i = 0; i < $scope.cars.length; i++) {
if ($scope.cars[i].type == $scope.typo) {
carhold.push($scope.cars[i].done)
};
};
$scope.carhold2 = carhold;
};
});
g.error(function (err){
$log.error(err);
});
}]);
JSON here
{
"id": 1,
"type": "Domestic",
"done": "Ford"
},
{
"id": 2,
"type": "Domestic",
"done": "Chrysler"
},
{
"id": 3,
"type": "Domestic",
"done": "Tesla"
},
{
"id": 4,
"type": "Foreign",
"done": "Mercedes Benz"
},
{
"id": 5,
"type": "Foreign",
"done": "BMW"
},
{
"id": 6,
"type": "Foreign",
"done": "Volvo"
},
{
"id": 7,
"type": "Foreign",
"done": "VW"
}
Code now doing what I was looking for.
Pushed entire object rather than specific value into new array.
$scope.getType = function (currentNavItem) {
$scope.typo = currentNavItem;
var carhold = [];
for (var i = 0; i < $scope.cars.length; i++) {
if ($scope.cars[i].type == $scope.typo) {
carhold.push($scope.cars[i]);
};
};
Then did ng-repeat thru new collection and animation appeared on all items.
<!--flip thru array via ng-repeat and apply animation-->
<div layout="row" layout-wrap>
<div flex="50" class="repeat-animation" ng-repeat="x in carhold2">
<div class="itemcard">
{{x.done}}
</div>
</div>
</div>
Hey there I'm new to js Angular and can't figure out what I've done wrong, how do I put an object method inside the ng-click function:
<div class="container" ng-repeat="exercise in exercises">
<div class="row">
<div class="exercise-icon col-xs-2">
<img ng-src="{{ exercise.icon }}">
</div>
<div class="col-xs-6">
<p class="exercise-name"> {{ exercise.name }} </p>
</div>
<div class="col-xs-4 counters">
<span class="decrease">-</span><span class="count"> {{ exercise.count }} </span>
<span class="increase" ng-click="{{exercise.increase($index)}}">+</span>
</div>
</div>
This is the controller script:
app.controller('MainController', ['$scope', function($scope) {
$scope.exercises = [
{
icon: 'img/pushup.jpg',
name: 'Pushups',
count: 20
},
{
icon: 'img/squat.jpg',
name: 'Squats',
count: 15
},
{
icon: 'img/pullup.jpg',
name: 'Pullups',
count: 10
},
{
icon: 'img/row.jpg',
name: 'Rows',
count: 10
},
{
icon: 'img/lunge.jpg',
name: 'Lunges',
count: 10
},
{
icon: 'img/stepup.jpg',
name: 'Step Ups',
count: 10
},
{
icon: 'img/situp.jpg',
name: 'Sit Ups',
count: 15
}
];
$scope.increase = function($index) {
$index.count++;
};
}]);
The exercise icon, name and count are all showing however the click function is not working for some reason, is the syntax correct for inserting a object method into a ng-click? I couldn't find any applicable answers online.
The functionality I would expect is count to increase everytime + is pressed.
There are 2 points wrong here, you're calling your function wrongly:
{{exercise.increase($index)}}
should be
increase($index)
and you're treating $index as an object, it should be like so:
$scope.increase = function($index) {
$scope.exercises[$index].count++;
};
Change:
<span class="increase" ng-click="{{exercise.increase($index)}}">+</span>
to:
<span class="increase" ng-click="exercise.increase($index)">+</span>
The braces aren't needed in Angular.
You can achieve your result without calling a function and doing stuff just inside ng-click itself.
<span class="increase" ng-click="exercises.count =exercises.count+1 ">+</span>
try this one
<span class="increase" ng-click="increase($index)">+</span>
and you controller
$index = $index + 1;
In my Code, I Created sample json data (Like Var Flensburg) in the view for Flensburg City. These Data Includes Name,Short-text and Images. So With This code I can show all this Places inside Flensburg with Name, Short-text and Images.I want to change my code which I mentioned in comment section in code.My Code is as follows-
Modified Code
#model PoiFinder.Models.City
<div class="row wrapper border-bottom white-bg page-heading">
<div class="col-lg-10">
<h2>#ViewBag.Title</h2>
<ol class="breadcrumb">
<li class="active">
Back
</li>
</ol>
</div>
</div>
<script src="http://maps.google.com/maps/api/js?sensor=true" type="text/javascript"></script>
<style>
#map_canvas img {
max-width: none;
}
</style>
<style>
.infoDiv {
height: 200px;
width: 300px;
-webkit-user-select: none;
background-color: white;
}
</style>
<div id="map_canvas" style="height: 600px;"></div>
#section scripts {
<section class="scripts">
<script type="text/javascript">
$.ajax({
url: '#Url.Action("GetGeoData", "Home")',
type: 'GET',
success: function (getGeoData) {
Initialize(getGeoData);
}
});
$(document).ready(function () {
Initialize();
});
function Initialize() {
google.maps.visualRefresh = true;
var Flensburg = new google.maps.LatLng(54.78194444, 9.43666667);
var mapOptions = {
zoom: 14,
center: Flensburg,
mapTypeId: google.maps.MapTypeId.G_NORMAL_MAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
var myLatlng = new google.maps.LatLng(54.78194444, 9.43666667);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Tate Gallery'
});
marker.setIcon('http://maps.google.com/mapfiles/ms/icons/green-dot.png')
$.each(getGeoData, function (i, item) {
var marker = new google.maps.Marker({
'position': new google.maps.LatLng(item.GeoCoordinates.Longitude, item.GeoCoordinates.Latitude),
'map': map,
'title': item.Name
});
marker.setIcon('http://maps.google.com/mapfiles/ms/icons/blue-dot.png')
var infowindow = new google.maps.InfoWindow({
content: "<div class='infoDiv'><h1>"+item.Name+"</h1><h5>" + item.Shorttext + "</h5>" + "<div><img src="+item.Images+"></div></div>"
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
})
}
</script>
</section>
}
Now What I want to do I want to make it Dynamic suppose in my App_data I stored many Json File of city with its interesting places and images. An Example is in Kiel.json file i stored data like this,
{
"poi": [
{
"Name": "Laboe Naval Memorial",
"Shorttext": "The Laboe Naval Memorial is a memorial located in Laboe, near Kiel, in Schleswig-Holstein, Germany. Started in 1927 and completed in 1936, the monument .",
"GeoCoordinates": {
"Longitude": 10.23079681,
"Latitude": 54.41218567
},
"Images": [
"https://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Marine_-_Ehrenmal_Laboe.jpg/300px-Marine_-_Ehrenmal_Laboe.jpg"
]
},
{
"Name": "Zoological Museum of Kiel University",
"Shorttext": "The Zoological Museum of Kiel University is a zoological museum in Kiel, Germany. It was founded by naturalist Karl Möbius, and architect Martin Gropiu.",
"GeoCoordinates": {
"Longitude": 10.14416695,
"Latitude": 54.32805634
},
"Images": [
"https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Zoologisch-Voelkerkundl_Museum_Kiel_1.jpg/400px-Zoologisch-Voelkerkundl_Museum_Kiel_1.jpg"
]
},
{
"Name": "Kieler Förde",
"Shorttext": "Kieler Förde is an approximately 17 km long inlet of the Baltic Sea on the eastern side of Schleswig-Holstein, Germany. Formed by glacial movement during the las.",
"GeoCoordinates": {
"Longitude": 10.17305556,
"Latitude": 54.36777778
},
"Images": [
"https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/Kiel_Luftaufnahme.JPG/400px-Kiel_Luftaufnahme.JPG"
]
},
{
"Name": "German submarine U-995",
"Shorttext": "German submarine U-995 is a Type VIIC/41 U-boat of Nazi Germany's Kriegsmarine. She was .",
"GeoCoordinates": {
"Longitude": 10.22888889,
"Latitude": 54.4125
},
"Images": [
"https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/U995_2004_1.jpg/400px-U995_2004_1.jpg"
]
}
.............. so on.
I want to get Name, Shorttext, Images from this Kiel.json file in my code. As I am very new in handling this situation I could not get logic how to proceed.
I created Json object in the model class like this-
public class GeoCoordinates
{
public double Longitude { get; set; }
public double Latitude { get; set; }
}
public class Poi
{
public string Name { get; set; }
public string Shorttext { get; set; }
public GeoCoordinates GeoCoordinates { get; set; }
public List<string> Images { get; set; }
}
public class RootObject
{
public List<Poi> poi { get; set; }
}
My Controller class to take the name is as follows-
[HttpPost]
public ActionResult Index(City objCityModel)
{
string name = objCityModel.Name;
return View();
}
public ActionResult GoogleMap(City objCityModel)
{
string name = objCityModel.Name;
ViewBag.Title = name;
return View();
}
public JsonResult GetGeoData(City objCityModel)
{
string name = objCityModel.Name;
ViewBag.Title = name;
string appDataPath = Server.MapPath(#"~/App_Data/POI_Json/");
string file = Path.Combine(appDataPath, "Kiel.json");
if (System.IO.File.Exists(file))
{
using (StreamReader stream = new StreamReader(file))
{
string jsonData = stream.ReadToEnd();
var json = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonData, typeof(RootObject));
return Json(json, JsonRequestBehavior.AllowGet);
}
}
return Json(null, JsonRequestBehavior.AllowGet);
}
I create a textbox and button in index view to go according to the city name. I just give this code for understanding-
#using (Html.BeginForm("GoogleMap", "Home"))
{
<div class="wrapper wrapper-content">
#Html.TextBoxFor(m => m.Name)
<label for="somevalue">City Name</label>
<div class="input-group-btn">
<button id="mapViewBtn" class="btn btn-primary" type="submit">Map View</button>
}
</div>
</div>
}
Create an action which will return your json Data.
call it from ajax .
public JsonResult GetgeoData()
{
using (StreamReader sr = new StreamReader(Server.MapPath("~/App_Data/Kiel.json")))
{
var getData = JsonConvert.DeserializeObject<RootObject>(sr.ReadToEnd());
return Json(getData, JsonRequestBehavior.AllowGet);
}
}
Call this action before calling Initialize(); add a parameter to your Initialize function.
like
$.ajax({
url: '#Url.Action("GetgeoData", "yourcontrollername")',
type: 'GET',
success: function (getGeoData) {
Initialize(getGeoData.poi);
}
});
and inside your Initialize function.
run the each loop
$.each(getGeoData, function (i, item) {
var marker = new google.maps.Marker({
'position': new google.maps.LatLng(item.GeoCoordinates.Longitude, item.GeoCoordinates.Latitude),
'map': map,
'title': item.Name
});