tytan tytan - 5 months ago 6
Javascript Question

AngularJS manipulate parent's DOM in directive

I am new in AngularJS. I have searched some pages about how to manipulate DOM in directive, but most of them are manipulating the DOM of directive itself. My problem is manipulate the DOM outside of the directive.

There is a Google Map in my project, and there are some markers on the map to show events. What I want to do is that when clicking the marker, the application should show the detailed information of the event in a slide bar. Based on the code below, the requirement is when I click the marker which triggers updateMarkers() in directive, it should change the value of {{detail}} in HTML. What I am doing now is trying to use "=" to give directive access to the values in its controller scope, but this way does not work. So please offer some help if you know, thank you.


<div id="wrapper" >
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
<app-map id="map" center="loc" markers="cities" details="details" show-detail="getDetails(directivedata)" on-init="gotoCurrentLocation(directiveData)"> </app-map>

Part of controller:

app.controller("appCtrl", function ($scope, $http) {
$scope.details = "something"; //should be changed when click markers in map


app.directive("appMap", ['$http', function ($http) {
return {
restrict: "E",
replace: true,
template: "<div></div>",
scope: {
center: "=", // Center point on the map (e.g. <code>{ latitude: 10, longitude: 10 }</code>).
markers: "=", // Array of map markers (e.g. <code>[{ lat: 10, lon: 10, name: "hello" }]</code>).
details: "=", //used for resend a REST api and store data in here
width: "@", // Map width in pixels.
height: "@", // Map height in pixels.
zoom: "@", // Zoom level (one is totally zoomed out, 25 is very much zoomed in).
mapTypeId: "@", // Type of tile to show on the map (roadmap, satellite, hybrid, terrain).
panControl: "@", // Whether to show a pan control on the map.
zoomControl: "@", // Whether to show a zoom control on the map.
scaleControl: "@", // Whether to show scale control on the map.
onInit: "&",
showDetail: "&"
link: function (scope, element, attrs) {
//some code.....
function updateMarkers() {
if (map && scope.markers.length > 0) {
window.alert("get me");
// clear old markers
if (currentMarkers != null) {
for (var i = 0; i < currentMarkers.length; i++) {

window.alert("get here1*****");
// create new markers
currentMarkers = [];
var markers = scope.markers;

function makeHappen(thi){
return function(){
scope.details = thi;
window.alert("***" + "in directive " + thi);

for (var i = 1; i < markers.length-1; i++) {
var m = markers[i];
if(m.venue == null || m.venue.lat == 0.0)
var loc = new google.maps.LatLng(m.venue.lat, m.venue.lon);
var eventName = m.description;
var mm = new google.maps.Marker({ position: loc, map: map, title: m.name, id: m.id, count: i});
mm.addListener('click', makeHappen(eventName), false);



Use . notation to properly enable two way data binding. details is a primitive type in your controller. Though the isolate scope in directive can access details, when you assign something to details in the makeHappen function, it creates a new details in the isolate scope.

In this case, instead of a primitive type $scope.details in your controller, make it an object e.g: $scope.details = {msg: 'something' }. Print it in template i.e: {{details.msg}}. Change details to details.msg in your makeHappen function of your isolate scope.

(I am answering from mobile. Will update the answer with more info/link later.)