isolate scope communication from directive to directive? - angularjs

I am new to AngularJS and got confused with directive concept.
I am updating scope.markers in my second directive via $scope.delete function but changes are not reflecting on first directives,as I am using two way data binding isolate scope, so it should reflect. any solution will be a great help.
I have my first directive as:
app.directive('damageDiagram', function () {
return {
retrict: 'AE',
scope: {
imgsrc: '=', markers: '=', pointsrc: '=', dtype:'='
},
templateUrl: 'app/components/inspections/damage-diagram.html',
link: function (scope, element, attrs) {
}
}
});
and second directive as:
app.directive('damageMarker', function ($mdDialog,inspectionService,$timeout) {
return {
restrict: 'AE',
require: '?^damageDiagram',
scope: {
marker: '=',
pointsrc: '=',
dtype:'=',
markers: '='
},
template: '<img ng-src="{{pointsrc}}" />',
link: function (scope, elem, attr) {
elem.on("click",function(e){
showDialog();
function showDialog($event) {
var parentEl = angular.element(document.body);
$mdDialog.show ({
parent: parentEl,
targetEvent: $event,
template:
'<form name="clientForm" novalidate >'+
'<md-dialog aria-label="List dialog">' +
' <md-dialog-content>'+
'<md-input-container>'+
'<md-select ng-model="dtypeValue" class="dialog-close" placeholder="Select dtype">'+
'<md-option ng-repeat="opt in dtype">{{opt}}</md-option>'+
'</md-select>'+
'</md-input-container>'+
'<md-input-container class="md-block">'+
'<label>Comment</label>'+
'<input required name="name" ng-model="comment" class="dialog-close">'+
'<div ng-messages="clientForm.name.$error">'+
'<div ng-message="required">This is required.</div>'+
'</div>'+
'</md-input-container>'+
' </md-dialog-content>' +
' <div class="md-actions" layout="row" layout-align="end center">' +
' <md-button ng-click="closeDialog()" class="md-primary">' +
' Close' +
' </md-button>' +
'<md-button ng-disabled="clientForm.$invalid" ng-click = "save()" class="md-primary">'+
'Save'+
'</md-button>'+
'<md-button ng-disabled="clientForm.$invalid" ng-click = "delete()" class="md-primary">'+
'Delete'+
'</md-button>'+
' </div>' +
'</md-dialog>'+
'</form>',
controller: DialogController
});
function DialogController($scope, $mdDialog) {
$scope.dtypeValue = scope.dtype[scope.marker.dtype.toUpperCase()];
$scope.dtype = scope.dtype;
$scope.comment = scope.marker.comment;
$scope.marker = scope.marker;
$scope.closeDialog = function() {
$mdDialog.hide();
}
$scope.save = function(){
console.log($scope.marker.id);
console.log($scope.dtypeValue);
console.log($scope.comment);
var dataSend = {};
dataSend.id = $scope.marker.id;
dataSend.comment = $scope.comment;
for(var key in $scope.dtype) {
if($scope.dtype[key] == $scope.dtypeValue) {
dataSend.dtype = key;
}
}
inspectionService.updateDiagram(dataSend).then(function(response){
console.debug("response ; "+response);
$mdDialog.hide();
scope.marker.id = response.id;
scope.marker.comment = response.comment;
scope.marker.dtype = response.dtype;
});
}
$scope.delete = function(){
var dataSend = {};
dataSend.id = $scope.marker.id;
var param = {};
param.inspection=$scope.marker.inspection;
inspectionService.deleteDiagramMarker(dataSend).then(function(response){
inspectionService.getDiagram(param).then(function(response){
$timeout(function() {
scope.$apply(function(){
scope.markers = response.results;
})
},2000);
console.debug("response ; "+response);
$mdDialog.hide();
});
});
}
}
}
});
console.log(scope.marker.top, scope.marker.left, elem);
}
}
});
My html code for damage-diagram directive is as follows:
<damage-diagram imgsrc="imgsrc" pointsrc="pointsrc" dtype="dtype"
markers="inspection.damage_diagram">
</damage-diagram>
and my html code for damage-directive is as follow:
<div style="position:relative">
<img id="23467129" ng-src="{{imgsrc}}" style="position:relative" width="100%" />
<div ng-repeat="marker in markers"
marker="marker"
markers="markers"
dtype="dtype"
pointsrc="pointsrc"
damage-marker>
</div>
</div>
controller is as follows:
app.controller('InspectionDetailCtrl', ['$scope', 'inspectionService', '$stateParams', 'Restangular','$rootScope',
function ($scope, inspectionService, $stateParams, Restangular, $rootScope) {
$scope.updateDamageImage = {};
$scope.insp_id = $stateParams.inspId;
$scope.damageImagesShow = false;
$scope.comments = [];
$scope.types = [];
$scope.selectTypeDelete = false;
$scope.commentDelete = false;
$scope.selectTypeDeleteBefore = true;
$scope.commentDeleteBefore = true;
init($scope.insp_id);
console.log("Fetching details for scope", $scope.insp_id);
function init(insp_id)
{
inspectionService.inspections.customGET(insp_id, {type: 'full'})
.then(function (data) {
$scope.inspection = data;
}, function (err) {
$scope.inspection = null;
});
}
$scope.pointsrc="app/components/inspections/pointer.png";
$scope.dtype = {
'S': 'Scratch (minor)',
'DS': 'Deep Scratch',
'D': 'Dents',
'WD': 'Wheel Damage',
'CW': 'Cracked Window',
'FT': 'Flat Tire',
'BL': 'Broken (lights)'
};
}]);

First of all two way binding in directive doesn't works like that any change reflected in main controller can be seen in directive but not other way any change in directive won't be reflected in main controller.
But there is a solution you can create an object in main controller
var x={};
x.value='to be passed in directive'
then you use same variable in directive since only once instance of object is created so any change in any directive will be reflected everywhere.

Related

Use same functions over different arrays in Angular directive

I'm really new to AngularJS and I'm having difficulties when trying to reuse functions over different arrays,actually its just one array and it has 2 more inside him.Can anyone tell me where I'm wrong,please.Thank you.
<body ng-controller="MainCtrl as mainCtrl">
<my-dates ng-repeat="item in mainCtrl.list"></my-dates>
</body>
app.directive('myDates', function() {
return {
// scope:{options:'&'},
restrict:'E',
template:'<table class="myTable">' +
'<tr>'+
'<th><input type="checkbox" ng-model="selectedAll" ng-click="mainCtrl.checkAll()"></th>'+
'<th>Start Date:</th>'+
'<th>End Date:</th>'+
'<th>Hours:</th>'+
'<th>Status:</th>'+
'</tr>'+
'<tr ng-repeat = "items in item">'+
'<td><input type="checkbox" ng-model="items.selected"></td>'+
'<td>{{items.start}}</td>'+
'<td>{{items.end}}</td>'+
'<td>{{items.hours}}</td>'+
'<td>{{items.selected}}</td>'+
'</tr>'+
'</table>'+
'<button class="myButton" ng-click="mainCtrl.add()">Add element</button>'+
'<button class="myButton" ng-click="mainCtrl.remove()">Remove element</button>'
}
});
app.controller('MainCtrl', function ($scope, $modal ,$log) {
var self = this;
self.list = [[{start:1,end:15,hours:7,selected: false},{start:2,end:14,hours:6,selected: false},{start:3,end:13,hours:5,selected: false},{start:1,end:15,hours:7,selected: false},{start:2,end:14,hours:6,selected: false},{start:3,end:13,hours:5,selected: false}],
[{start:1,end:15,hours:7,selected: false},{start:1,end:15,hours:7,selected: false}]];
self.allSelected = false;
self.add = function () {
var modalInstance = $modal.open({
template: '<div class="modal-header"><h1>Add element to array</h1></div>'+
'<div class="modal-body">'+
'<div>'+
'<span>Enter Start Date:</span>'+
'<input ng-model="object.start" type="text"/>'+
'</div>'+
'<div>'+
'<span>Enter End Date:</span>'+
'<input ng-model="object.end" type="text"/>'+
'</div>'+
'<div>'+
'<span>Enter Work Hours:</span>'+
'<input ng-model="object.hours" type="text"/>'+
'</div>'+
'</div>'+
'<div class="modal-footer">'+
'<button class="btn btn-primary" ng-click="ok()">OK</button>'+
'<button class="btn btn-warning" type="button" ng-click="close()">Cancel</button>'+
'</div>',
controller: 'PopupCont',
resolve: {
items: function () {
return $scope.items;
}
}
});
modalInstance.result.then(function (object) {
self.list.push(object);
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
}
self.remove = function() {
console.log('tc');
self.list = self.list.filter(
function(item) {
return !item.selected
}
);
}
self.checkAll = function(){
if ($scope.selectedAll) {
$scope.selectedAll = true;
} else {
$scope.selectedAll = false;
}
angular.forEach(self.list, function(item) {
item.selected = $scope.selectedAll;
});
}
});
app.controller('PopupCont', ['$scope','$modalInstance',function ($scope, $modalInstance) {
$scope.object = {start:undefined,end:undefined,hours:undefined};
$scope.ok = function () {
$modalInstance.close($scope.object);
};
$scope.close = function () {
$modalInstance.dismiss('cancel');
}
}]);
I think you want to do the following:
Plunkr
At the moment your code doesn't know which list to select, so a couple of changes:
'<button class="myButton" ng-click="mainCtrl.add($index)">Add element</button>'+
'<button class="myButton" ng-click="mainCtrl.remove($index)">Remove element</button>
'
Then in the add:
self.add = function (index) {
refer to the index:
modalInstance.result.then(function (object) {
console.log(object)
self.list[index].push(object);
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
And also in the remove:
self.remove = function(index) {
console.log('tc');
self.list[index] = self.list[index].filter(
function(item) {
return !item.selected
}
);
Is that what you want?

Calling parent directive method from child directive through attrs

This is the scenario :
<export-team>
<ul>
<li>
<button buy-ticket="{{data}}" buy-callback="onBuyTicket()">buy</button>
</li>
<li>
<button buy-ticket="{{data}}" buy-callback="onBuyTicket()">buy</button>
</li>
</ul>
</export-team>
The buyTicket directive
(function() {
'use strict';
angular
.module('myApp')
.directive('buyTicket', buyTicket);
/** #ngInject */
function buyTicket($parse, ngDialog, authService, APPCONFIG, $rootScope, shareToken, contestsFactory, shareCurrentTicket, shareIdSession, shareSessionAAMS, $location) {
var vm = this;
var directive = {
restrict: 'A',
link : function(scope, element, attributes) {
var buyCompatible = attributes['buyCompatible'];
function addZero(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
var buyTicket = function(contest) {
var d = new Date();
var y = d.getFullYear();
var m = addZero(d.getMonth()+1);
var day = addZero(d.getDate());
var h = addZero(d.getHours());
var min = addZero(d.getMinutes());
var s = addZero(d.getSeconds());
var date = ''+y+m+day+h+min+s+'';
var transactionId = $rootScope.TRANSACTIONID;
var currentTOKEN = shareToken.get();
var data = {
idSessione:currentTOKEN, // ->TOKEN
userAgent:navigator.userAgent,
sessioneAAMS:contest.aams_session_id,
gameId:APPCONFIG.GAME_ID,
transactionId:transactionId,
dateTime:date,
buyIn:contest.buy_in
}
var dialogLoading = ngDialog.open({
closeByDocument : false,
closeByEscape : false,
showClose : false,
id : 'ft-modal-loading',
controller: ['$scope', function($scope){
$scope.bodyUrl = 'app/components/modals/body/loading.html';
$scope.title = 'Acquisto Ticket';
$scope.error = 'Il sistema sta procedendo all\'acquisto del ticket';
}]
});
contestsFactory.buyTicket(data).success(function(response){
dialogLoading.close();
if (response.esito == "0") {
if (!buyCompatible) {
shareCurrentTicket.set(response.ticketSogei);
shareSessionAAMS.set(contest.aams_session_id);
shareIdSession.set(contest.id_session);
$location.path('my-contests/'+contest.id_contest+'/'+contest.contest_status);
}
} else {
var message = response.descrizione;
var ids = ngDialog.getOpenDialogs();
var dialogError = ngDialog.open({
id : "ft-modal-error-2",
controller: ['$scope', function($scope){
$scope.bodyUrl = 'app/components/modals/body/error.html';
$scope.title = 'Errore';
$scope.error = message;
}]
});
}
})
.error(function(){
var dialogErrorNotEndled = ngDialog.close('ft-modal-loading');
ngDialog.open({
id : 'ft-modal-error',
controller: ['$scope', function($scope){
$scope.bodyUrl = 'app/components/modals/body/error.html';
$scope.title = 'Errore';
$scope.error = 'Il servizio non รจ attualmente disponibile';
}]
});
})
}
var openConfirmBuyTicket = function(contest) {
contest = JSON.parse(contest);
if (ngDialog.isOpen('ft-modal-contest-detail')) {
ngDialog.close('ft-modal-contest-detail');
};
if (!authService.isLogged()) {
ngDialog.open({
controller: ['$scope', function($scope){
$scope.bodyUrl = 'app/components/modals/body/not_logged.html';
$scope.title = 'Spiacenti';
$scope.error = 'Devi essere loggato per poter partecipare ad un contest';
}]
});
} else {
ngDialog.openConfirm({
controller: ['$scope', function($scope){
$scope.title = 'CONFERMA';
$scope.bodyUrl = 'app/components/modals/body/confirm_buy.html';
$scope.contest_name = contest.name_contest;
$scope.buy_in = contest.buy_in;
$scope.currency = APPCONFIG.CURRENCY_SYMBOL;
}],
}).then(function (confirm) {
buyTicket(contest);
}, function(reject) {
});
}
}
element.on('click', function(e){
var contest = attributes['buyTicket'];
openConfirmBuyTicket(contest);
})
}
};
return directive;
}
})();
The export directive
(function() {
'use strict';
angular
.module('myApp')
.directive('exportTeam', exportTeam);
/** #ngInject */
function exportTeam(contestsFactory, ngDialog, APPCONFIG, formatDateFactory) {
var vm = this;
var directive = {
restrict: 'AE',
transclude: true,
controller : function($scope) {
$scope.test = function() {
alert('hey');
}
},
link : function(scope, element, attributes) {
element.on('click', function(e){
var ticket = attributes['exportTeam'];
var id_session = attributes['idsession'];
scope.openExportTeamDialog(ticket, id_session, false);
})
scope.openExportTeamDialog = function(ticket, aams_session_id, afterSave) {
ngDialog.open({
id : 'ft-modal-exportTeam-detail',
className : 'ngdialog ngdialog-theme-default ft-dialog-exportTeam',
controller: ['$scope', 'contestsFactory', 'APPCONFIG', function($scope, contestsFactory, APPCONFIG){
$scope.title = "Aggiungi contest compatibili";
$scope.bodyUrl = 'app/components/modals/body/exportTeam.html';
$scope.contentLoading = true;
$scope.currency = APPCONFIG.CURRENCY_SYMBOL;
$scope.afterSave = afterSave;
$scope.CompatibleContests = [];
contestsFactory.getCompatibleContests(ticket).then(function(response){
angular.forEach(response.data[0], function(item, i){
var multientryOptions = [];
if(item.multientry > 1) {
item.isMultientry = false;
var n = parseInt(item.multientry);
for (i = 1; i <= n; i++) {
multientryOptions.push({
text : i+" team",
value : i
})
}
item.multientryOptions = multientryOptions;
item.multientryOptionSelected = multientryOptions[0];
}else{
item.isMultientry = true;
};
})
$scope.CompatibleContests = response.data[0];
$scope.contentLoading = false;
})
}]
});
}
scope.openExportTeamDialog('N3E94100A725F9QG', 'M3E921013C6DCFCT', false);
}
};
return directive;
}
})();
The buy-ticket directive makes an http call, on the response i want to be able to call the onBuyTicket method of the <export> directive.
I'm trying to understand the best way to do that.
Thanks everyone
This sample show to you how can call an function from your directive
In this sample you can see we just insert data in our directive, and then we handle the data and other action in the directive.
var app = angular.module("app", []);
app.controller("ctrl", function ($scope) {
$scope.dataFromYourController = [
{ name: "Concert Jennifer", value: 200 },
{ name: "007", value: 100 }
];
})
.directive("export", function () {
var template = "<div>" +
"<ul>" +
"<li ng-repeat=\"array in arrays\">" +
"<button ng-click=\"onBuyTicket()\">buy Ticket {{array.name}}</button><hr>" +
"</li>" +
"</ul>" +
"</div>";
return {
restrict: "E",
template: template,
scope: {
data: "="
},
link: function (scope, elem, attrs, ngModel) {
scope.arrays = scope.data;
scope.onBuyTicket = function () {
alert("calling function from directive");
}
}
};
})
<!doctype html>
<html ng-app="app" ng-controller="ctrl">
<head>
</head>
<body>
<h1>call action from your directive</h1>
<export data="dataFromYourController"></export>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</body>
</html>
#eesdil
var directive = {
restrict: 'AE',
transclude: true,
controller : function($scope) {
$scope.onBuyTicket = function() {
alert('hey');
}
}
}
Ho can I call that from the buy-ticket directive ?
Use the $parent
<button buy-ticket="{{data}}" buy-callback="$parent.onBuyTicket()">buy</button>
So the expor directive something like:
var directive = {
restrict: 'AE',
template: '<ng-tansclude></ng-transclude>',
transclude: true,
controller : function($scope) {
$scope.onBuyTicket = function() {
alert('hey');
}
}
}
UPDATED:
see the plunker:
https://plnkr.co/edit/fmyJ4oPLvTiI0TzO7h1b?p=preview
It really depends what you can call and what you cannot based on the scopes... here if you would remove the scope from the export directive would work without the $parent also as export would share the same scope as the parent (main view)
The best way to communicate events from a child directive to a parent directive (or controller) is to use the $emit method of the scope.
What you want to do is take an ng-click event, get additional information with an $http call, and $emit an event with the additional information to be used by your parent directive (or controller).
HTML
<button buy-ticket="data" ng-click="onBuyTicket()">buy</button>
The directive:
angular.module("myApp").directive("buyTicket", function($http) {
function linkFn(scope,elem,attrs) {
scope.onBuyTicket = function() {
var buyData = scope.$eval(attrs.buyTicket);
var url = someFunction(buyData);
$http.get(url).then (function (response) {
var httpData = response.data;
scope.$emit("buyTicket.click", buyData, httpData);
});
};
};
return {
restrict: "AE",
link: linkFn
};
});
In the parent controller:
$scope.$on("buyTicket.click", function (buyData, httpData) {
console.log(buyData);
console.log(httpData);
});
Notice that I used the $eval method to get the data from the variable named by the buy-ticket attribute.
When choosing a name for the event, I recommend including the name of the directive in the event's name. It makes it clear the source of the event and is unlikely to be duplicated elsewhere.

How to get ng-model value from directive to controller in Angular?

I created a custom directive in which I have given text box and I want to take that model value in my controller.
I tried to find it, but didn't success.
here is my directive code
app.directive("bhAddCategory", ["$rootScope", "$timeout", "CategoryFactory", "ArticleFactory", "RecentArticleFactory", "focus", function ($rootScope, $timeout, CategoryFactory, ArticleFactory, RecentArticleFactory, focus) {
return {
scope: {
display: '=bhCategoryToggle',
imageOverflow: '=bhImageOverflow',
textBoxCss: '#bhTextBoxCss',
rmText: '=bhRmText'
},
replace: true,
template: '<div>' +
'<div class="pull-left forDrop"><input type="text" focus-on="focusMe" ng-class="myColonyList" class="effect1" placeholder="Add a colony" data-ng-model="newCategoryName" data-ng-trim="true" ng-keypress="pressEnter($event)"></div>' +
'<div class="pull-right"><img src="/images/greyplus.png" ng-class="{imageoverflow: imageOverflow}" ng-show="loadplus" data-ng-click="addCategory()" alt="add category"><img src="/images/loader.gif" ng-class="{imageoverflow: imageOverflow}" alt="" ng-show="loadgif" class="colonyloder"></div >' +
'</div>',
link: function (scope, element, attrs) {
scope.loadplus = true;
scope.pressEnter = function (keyEvent) {
if (keyEvent.which === 13)
scope.addCategory();
};
scope.resetNewCategoryName = function () {
if (scope.rmText) {
scope.newCategoryName = '';
}
};
scope.addCategory = function () {
scope.display = false;
var addNewCat = scope.newCategoryName;
commonNotification($rootScope, true, false, '', '');
var categoryData = {
category_name: addNewCat,
category_type: 0
};
if (addNewCat !== undefined && addNewCat !== '') {
scope.loadgif = true;
var category_details = CategoryFactory.nameExists(addNewCat);
if (!category_details.exist) {
CategoryFactory.addAtPostion(categoryData, category_details.mid)
.then(function (category) {
scope.loadgif = false;
scope.resetNewCategoryName();
commonNotification($rootScope, false, true, true, category.success);
$timeout(function () {
$rootScope.newStatus = false;
}, 3000);
}, function (error) {
commonNotification($rootScope, false, true, true, error.message);
$timeout(function () {
$rootScope.newStatus = false;
}, 3000);
});
} else {
scope.loadgif = false;
commonNotification($rootScope, false, true, true, 'Category name already exists!');
$timeout(function () {
$rootScope.newStatus = false;
}, 2000);
}
} else {
commonNotification($rootScope, false, true, true, 'Category name is required!');
$timeout(function () {
$rootScope.newStatus = false;
}, 2000);
}
};
}
};
}]);
And here is my controller
app.controller('bookmarkCtrl', ["$scope", "$http", "$rootScope", "$timeout", "RecentArticleFactory", "CategoryFactory", "ArticleFactory", "focus", "debounce", "userFactory", function ($scope, $http, $rootScope, $timeout, RecentArticleFactory, CategoryFactory, ArticleFactory, focus, debounce, userFactory) {
}]);
Can I get any working demo, so that I can understand and implement in my code
Thanks in Advance
Use a parent scope excecution parameter on your directive.This is a scope function which is declared on your parent controller and is invoked from within your directive whenever you want to pass something to your controller.
To accomplish this we declare a scope parameter in our directive with the '&' prefix
See this example which i created for another answer
http://jsfiddle.net/jwd3gywz/26/
JS
angular.module('components', []).controller('Composer', function Composer($scope, $http) {
// adding snippet to composed text
$scope.composed_text = '';
$scope.updateCaretPosition=function(pos){
$scope.caret_position=pos;
console.log('called'+pos);
}
$scope.$watch('caret_position',function(){
console.log($scope.caret_position);
})
}).directive('caretPosition', function() {
return {
scope:{updateCaretPosition:'&'},
link: function(scope, element, attrs) {
element.bind('keyup click', function(e){
var caret_position = element[0].selectionStart;
scope.updateCaretPosition({pos:caret_position});
console.log('my current position: ' + caret_position);
});
}
}
});
angular.module('myApp', ['components'])
HTML
<!doctype html>
<html ng-app="myApp">
<body>
<div ng-controller="Composer">
<textarea class="form-control composed_text" ng-model="composed_text" update-caret-position="updateCaretPosition(pos)" caret-position="" rows="20"></textarea>
</div>
</body>
</html>

How to call function in directive from button click

How do I call a function in a directive from a button click? I have been trying and have come up with this (but it is not working):
HTML
<div ng-controller="myMapCTRL as myMapctrl">
<div id="panel">
<input ng-click="updateMap()" type=button value="Remove Path">
</div>
<my-map-with-path id="map-canvas" class="map-canvas" ng-if="dataHasLoaded" ></my-map-with-path>
</div>
Controller
app.controller('myMapCTRL', ['$scope', 'PathService', function($scope, PathService){
//console.log('in controller');
$scope.removed = false;
if(typeof $scope.paths ==='undefined') {
$scope.dataHasLoaded = false;
$scope.center = new google.maps.LatLng(51.5130300, -0.3202410);
PathService.getPaths().then(function(data){
$scope.paths = data;
$scope.dataHasLoaded = true;
//console.log('paths loaded');
});
};
}]);
Directive
app.directive('myMapWithPath', [function() {
return{
restrict: 'AE',
template: '<div></div>',
replace: true,
controller: 'myMapCTRL',
link: function(scope, element, attrs){
//console.log('in link');
scope.updateMap = function() {
console.log('inside updateMap()');
}
var map, path = new google.maps.MVCArray(),
service = new google.maps.DirectionsService(), poly;
//var center = new google.maps.LatLng(51.5130300, -0.3202410);
var myOptions = {
zoom: 15,
center: scope.center,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControlOptions: {
mapTypeIds: [google.maps.MapTypeId.ROADMAP, google.maps.MapTypeId.HYBRID,
google.maps.MapTypeId.SATELLITE]
},
disableDoubleClickZoom: true,
scrollwheel: false,
draggableCursor: "crosshair"
}
map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
poly = new google.maps.Polyline({ map: map });
for(var i = 0; i < scope.paths['j'].length; i++) {
var lat = scope.paths['j'][i]['k']
var lng = scope.paths['j'][i]['D']
var lat_lng = new google.maps.LatLng(lat, lng);
path.push(lat_lng);
}
poly.setPath(path);
google.maps.event.addListener(map, "click", function(evt) {
if (path.getLength() === 0) {
path.push(evt.latLng);
poly.setPath(path);
} else {
service.route({
origin: path.getAt(path.getLength() - 1),
destination: evt.latLng,
travelMode: google.maps.DirectionsTravelMode.DRIVING
}, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
for (var i = 0, len = result.routes[0].overview_path.length;
i < len; i++) {
path.push(result.routes[0].overview_path[i]);
}
}
});
}
//console.log(path);
});
}
}
}]);
I want to call scope.updateMap from the button click but it is not firing in the console.
This won't work because the ng-click is outside the directive.
You should move the function updateMap to the $scope of myMapCTRL
Having dug around a little more, it seems quite normal to use a shared service to communicate between a controller and a directive.
The general idea is this:
HTML
<div ng-controller="myMapCTRL as myMapctrl">
<div id="panel">
<input ng-click="updateMap()" type=button value="Remove Path">
</div>
<my-map-with-path id="map-canvas" class="map-canvas" ng-if="dataHasLoaded" ></my-map-with-path>
</div>
SharedService
app.factory('mySharedService', function($rootScope) {
var sharedService = {};
sharedService.doSomething = function() {
$rootScope.$broadcast('messageBroadcast');
};
return sharedService;
});
Controller
app.controller('myMapCTRL', ['$scope', 'mySharedService',
function($scope, sharedService){
$scope.updateMap = function() {
sharedService.doSomething();
}
}]);
Directive
app.directive('myMapWithPath', [function() {
return{
restrict: 'AE',
template: '<div></div>',
replace: true,
controller: 'myMapCTRL',
link: function(scope, element, attrs){
scope.$on('messageBroadcast', function() {
console.log('in directive broadcast message');
});
...
}
}
}]);
The idea seems to be that the controller calls a function in the shared service which "broadcasts" a message out. The directive waits for that message and when it is received, it does something amazing.
I am not sure if I need to inject the shared service into the directive or link function but it seems to work without it.

How to make AngularJS compile the code generated by directive?

Please help me on, How can we make AngularJS compile the code generated by directive ?
You can even find the same code here, http://jsbin.com/obuqip/4/edit
HTML
<div ng-controller="myController">
{{names[0]}} {{names[1]}}
<br/> <hello-world my-username="names[0]"></hello-world>
<br/> <hello-world my-username="names[1]"></hello-world>
<br/><button ng-click="clicked()">Click Me</button>
</div>
Javascript
var components= angular.module('components', []);
components.controller("myController",
function ($scope) {
var counter = 1;
$scope.names = ["Number0","lorem","Epsum"];
$scope.clicked = function() {
$scope.names[0] = "Number" + counter++;
};
}
);
// **Here is the directive code**
components.directive('helloWorld', function() {
var directiveObj = {
link:function(scope, element, attrs) {
var strTemplate, strUserT = attrs.myUsername || "";
console.log(strUserT);
if(strUserT) {
strTemplate = "<DIV> Hello" + "{{" + strUserT +"}} </DIV>" ;
} else {
strTemplate = "<DIV>Sorry, No user to greet!</DIV>" ;
}
element.replaceWith(strTemplate);
},
restrict: 'E'
};
return directiveObj;
});
Here's a version that doesn't use a compile function nor a link function:
myApp.directive('helloWorld', function () {
return {
restrict: 'E',
replace: true,
scope: {
myUsername: '#'
},
template: '<span><div ng-show="myUsername">Hello {{myUsername}}</div>'
+ '<div ng-hide="myUsername">Sorry, No user to greet!</div></span>',
};
});
Note that the template is wrapped in a <span> because a template needs to have one root element. (Without the <span>, it would have two <div> root elements.)
The HTML needs to be modified slightly, to interpolate:
<hello-world my-username="{{names[0]}}"></hello-world>
Fiddle.
Code: http://jsbin.com/obuqip/9/edit
components.directive('helloWorld', function() {
var directiveObj = {
compile:function(element, attrs) {
var strTemplate, strUserT = attrs.myUsername || "";
console.log(strUserT);
if(strUserT) {
strTemplate = "<DIV> Hello " + "{{" + strUserT +"}} </DIV>" ;
} else {
strTemplate = "<DIV>Sorry, No user to greet!</DIV>" ;
}
element.replaceWith(strTemplate);
},
restrict: 'E'
};
return directiveObj;
});
Explanation: The same code should be used in compile function rather than linking function. AngularJS does compile the generated content of compile function.
You need to create an angular element from the template and use the $compile service
jsBin
components.directive('helloWorld', ['$compile', function(compile) {
var directiveObj = {
link: function(scope, element, attrs) {
var strTemplate, strUserT = attrs.myUsername || "";
console.log(strUserT);
if (strUserT) {
strTemplate = "<DIV> Hello" + "{{" + strUserT +"}} </DIV>" ;
} else {
strTemplate = "<DIV>Sorry, No user to greet!</DIV>" ;
}
var e = angular.element(strTemplate);
compile(e.contents())(scope);
element.replaceWith(e);
},
template: function() {
console.log(args);
return "Hello";
},
restrict: 'E'
};
return directiveObj;
}]);

Resources