Angular placing functions - angularjs

I'm using the angular-google-maps library in my project. I have used a directive to load a custom google maps menu. The goal is to obviously reuse the directive. In the menu are a couple of buttons which when clicked should all carry out a function. I'm still trying to get my head around on how to do that, so here is my problem:
I would like to pan the map to its original position when the button "Home" is clicked. Normally that is just done with ng-click and the function is placed within the scope of the controller. With the directive I'm confused. Where should I place the "home()" function? Directive? Directive controller? Controller? I hope this makes any sense?!?!
HTML:
<div class="map_canvas">
<google-map center="map.center" zoom="map.zoom" draggable="true">
<marker ng-repeat="m in map.markers" coords="m" icon="m.icon" click="onMarkerClicked(m)">
<marker-label content="m.name" anchor="50 0" class="marker-labels"/>
<window ng-cloak coords="map.center" isIconVisibleOnClick="false" options="map.infowindows.options">
<p>This is an info window at {{ m.latitude | number:4 }}, {{ m.longitude | number:4 }}!</p>
<p class="muted">My marker will stay open when the window is popped up!</p>
</window>
</marker>
<map-custom-control position="google.maps.ControlPosition.TOP_CENTER" control-template="../templates/gmaps/main_menu.html" control-click=""></map-custom-control>
</google-map>
</div>
Template:
<div class="gmaps-menu">
<div class="gmaps-row">
<button type="button" class="btn btn-default"><img class="glyphicon-custom" src="../img/icons/glyphicons/glyphicons_020_home.png" ng-click="home()"></button>
<button type="button" class="btn btn-default"><img class="glyphicon-custom" src="../img/icons/glyphicons/glyphicons_349_fullscreen.png"></button>
<button type="button" class="btn btn-default"><img class="glyphicon-custom" src="../img/icons/glyphicons/glyphicons_096_vector_path_polygon.png"></button>
<button type="button" class="btn btn-default"><img class="glyphicon-custom" src="../img/icons/glyphicons/glyphicons_030_pencil.png"></button>
</div>
</div>
Directive:
AppDirectives.directive('mapCustomControl', ['$log', '$timeout', '$http', '$templateCache', 'google', 'GMapsLib' ,function ($log, $timeout, $http, $templateCache, google,GMapsLib) {
return {
restrict: 'E',
replace: true,
require: '^googleMap',
link: function(scope,element,attr,mapCtrl){
if (!angular.isDefined(attr.controlTemplate)) {
$log.error('map-custom-control: could not find a valid control-template property!');
return;
}
var templateUrl = attr.controlTemplate;
var position = google.maps.ControlPosition.TOP_CENTER;
if (angular.isDefined(attr.position)) {
var EVAL_IS_OK_WE_CONTROL_THE_INPUT = eval;
position = EVAL_IS_OK_WE_CONTROL_THE_INPUT(attr.position);
}
$timeout(function() {
var map = mapCtrl.getMap();
var controlDiv = document.createElement('div');
controlDiv.style.padding = '5px';
controlDiv.style.width = 'auto';
controlDiv.marginLeft = 'auto';
controlDiv.marginRight = 'auto';
$http.get(templateUrl, {cache: $templateCache})
.success(function(html) {
controlDiv.innerHTML = html;
})
.then(function (/*response*/) {
map.controls[position].push(controlDiv);
if (angular.isDefined(attr.controlClick)) {
google.maps.event.addDomListener(controlDiv, 'click', function() {
scope.$apply(attr.controlClick);
});
}
}
);
});
}
};
}]);

You can pass the scope function that has to be executed on the controller:
HTML
<div ng-app="app" ng-controller="sampleCtrl">
<maps-custom-control click-handler="alertMe()"></maps-custom-control>
</div>
JS
var app = angular.module('app', []);
app.directive('mapsCustomControl', function() {
return {
restrict: 'EA',
replace: true,
scope: {
clickHandler: '&'
},
template: '<div style="width: 100px; height:100px; background-color: red;" ng-click="clickHandler()"></div>'
};
});
app.controller('sampleCtrl', function ($scope) {
$scope.alertMe = function () {
window.alert('Refresh gMaps control');
};
});
Since we pass the alertMe function, this is the function that will get executed, I hope this makes sense?
Fiddle
A small remark on your code, it would be better if you get the template as follows:
app.directive('..', function() {
return {
template: '<div ng-include="getTemplate()"></div>',
link: function(scope, element, attr) {
scope.getTemplate = function() {
return this.attr.controlTemplate;
}
}
};
});
This way you don't need to do any strange ajax calls. Just add all the mark-up in your template and include it. don't make it necessary hard :-)

Related

angular bind html tags from controller to html view

I need to render the $scope.htmlView tags in to html view.
I already tried using ng-bind-html. It renders the html tags but scope variable values will not appear.
How can I render both html tags and and scope variable values?
This is the controller:
$scope.newObj = {
billStatus : true;
eventTime : "2015-01-10"
};
$scope.htmlView = '<p>{{newObj.eventTime}}</p> <div style="margin-top: -15px;"><md-checkbox ng-checked="{{newObj.billStatus}}" style="margin-left: 0px;" aria-label="Bilable"><span style="margin-left:0px;">Bilable</span> </md-checkbox></div>'
Expected result is:
<p> 2015-01-10</p>
<div style="margin-top: -15px;">
<md-checkbox ng-checked="true" style="margin-left: 0px;" aria- label="Bilable">
<span style="margin-left:0px;">Bilable</span>
</md-checkbox>
</div>
I search over the internet over days and still could't find out a way to figure out this. please help me. thank you.
You have to do 2 things.
Use data-ng-bind-html=""
Use $sce.trustAsHtml(string)
UPDATED:
If you wont to use angular expressions, you have to compile them using
$compile.
You can read more via this $SCE
I will tell you a long way but it will help you.Make a custom directive like this.
app.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.dynamic, function(html) {
ele.html(html);
$compile(ele.contents())(scope);
});
}
};
});
Use as
<span dynamic="{{htmlView}}" >
Hi please check this fiddle
https://plnkr.co/edit/iqNltdDYv2n9Agke0C2C?p=preview
HTML
<div ng-controller="ExampleController">
<p >{{newObj.eventTime}}</p>
<p dynamic="htmlView"></p>
</div
and JS
(function(angular) {
'use strict';
angular.module('bindHtmlExample', ['ngSanitize'])
.controller('ExampleController', ['$scope', function($scope) {
$scope.newObj = {
billStatus : true,
eventTime : "2015-01-10"
}
$scope.htmlView = '<p> {{newObj.eventTime}}</p> <div style="margin-top: -15px;">Hello <md-checkbox ng-checked="{{newObj.billStatus}}" style="margin-left: 0px;" aria-label="Bilable"><span style="margin-left:0px;">Bilable</span> </md-checkbox></div>'
}])
.directive('dynamic', function($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, element, attrs) {
scope.$watch(attrs.dynamic, function(html) {
element[0].innerHTML = html;
$compile(element.contents())(scope);
});
}
};
});
})(window.angular);

Variable value not passing in a controller using directive with ng-class

I am referencing the value of the variable in a controller in an ng-class template but its not working.
here is the html directive template URl :
<div class="tooltip-anchor">
<div class=" tooltip-content ehub-body" ng-class="{ 'tooltip__content--disabled': tooltipContentValue}" ng-transclude>Tooltip content</div>
</div>
Here is where i am using the directive in the index page
<div style="text-align:center;">
<ehub-tooltip>Hello i am here, and i am her to stay</ehub-tooltip>over here
<ehub-tooltip>Be nice to people on your way up and they will be nice to you on your way down</ehub-tooltip>click me
</div>
And here is the directive:
in this directive i am creating a variable and setting it to false and also trying to use it in an ng-class attribute
(function (window) {
'use strict';
angular
.module('ehub.component.tooltip', [])
.controller('ehubTooltipCtrl', ['$scope', function ($scope) {
$scope.tooltipContentValue = false;
}])
.directive('ehubTooltip', ehubTooltip);
function ehubTooltip() {
var directive = {
controller: "ehubTooltipCtrl",
link: link,
transclude: true,
templateUrl: 'ehub-tooltip.html',
restrict: 'E'
};
return directive;
function link(scope, element, attrs) {
scope.keyupevt = function () {
if (event.keyCode === 27) {
$scope.tooltipContentValue = true;
}
}
}
}
})();
Try this working jsfiddle.
angular.module('ExampleApp', ['ngMessages'])
.controller('ExampleController', function($scope) {
})
.directive('ehubTooltip', function() {
var directive = {
link: link,
transclude: true,
template: '<div class="tooltip-anchor"><div class=" tooltip-content ehub-body" ng-class="{ \'tooltip__content--disabled\': tooltipContentValue}" ng-transclude>Tooltip content</div></div>',
restrict: 'E'
};
function link(scope, element, attrs) {
scope.tooltipContentValue = false;
scope.keyupevt = function() {
if (event.keyCode === 27) {
scope.tooltipContentValue = true;
}
}
}
return directive;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="ExampleApp">
<div ng-controller="ExampleController">
<div style="text-align:center;">
<a href="" ng-keyup="keyupevt()">
<ehub-tooltip>Hello i am here, and i am her to stay</ehub-tooltip>over here</a>
<a href="" ng-keyup="keyupevt()">
<ehub-tooltip>Be nice to people on your way up and they will be nice to you on your way down</ehub-tooltip>click me</a>
</div>
</div>
</div>

how to test Bootstrap Modal in AngularJS using jasmine?

I am using bootstrap modal for displaying pop up's in angular app. It is working perfectly from front end but DOM elements inside pop up are not getting appended to the body
In the output, when I am displaying content of document, content of my html template is not getting appended to body tag. So I am unable to find/test any DOM element. It is not displaying any errors in console also.
Please any one can help me in resolving this issue by specifying how to test bootstrap modal in angular application using karma/jasmine.
angular.module("myApp").directive('popUp', ['$http', '$compile', function($http, $compile) {
return {
restrict: 'A',
replace: true,
scope: {
course: '=',
},
compile: function(element, cAtts){
var template,
$element,
loader;
var windowOpen = false;
loader = $http.get('components/popUp.view.html').success(function(data) {
template = data;
});
//return the Link function
return function(scope, element, lAtts) {
element.on('click', function(e) {
e.preventDefault();
$element = $( $compile(template)(scope) );
$element.modal({backdrop: 'static'});
windowOpen = true;
});
// if the template changes, we need to compile the current
// template again. just in case there are funky sticky things
scope.$watch('template', function(newValue, oldValue) {
if(newValue == undefined && oldValue == undefined) return;
if(windowOpen) return;
if(newValue == undefined){
//$(".modal").remove();
$element.remove();
$element = undefined;
return;
}
$element = $( $compile(template)(scope) );
});
};
}
}
}]);
My HTML Template:
<div id="{{handler}}" class="modal fade">
<div style="margin:-1px auto; width:90%;float:right;" class="modal-dialog">
<div style="padding-left: 25px; height:100vh;" class="modal-content">
<div class="modal-header navbar-static-top"><img src="content/assets/img/close.png" data-dismiss="modal" aria-hidden="true" ng-click="close()" title="Close" alt="Close" class="popUpClose close pull-left"/>
<div class="popUpTitle">
<div style="font-size:22px;">{{course.CourseName}}</div>
<div style="font-size:15px; margin-top:-5px;">{{course.CourseId}}</div><br/>
</div>
</div>
<div style="display:inline" class="modal-body">
<p>This is test Modal</p>
</div>
<div style="border:none;" class="modal-footer"> </div>
</div>
</div>
</div>
My Test File:
(function(){
"use strict";
describe("Testing Pop Up Directive Functionality", function(){
var $httpBackend, $scope, fakeData, $compile, $document;
var compileDirective, course, element, template;
beforeEach(module('myApp.testing'));
beforeEach(module('myApp'));
beforeEach(inject(function ($injector, _$templateCache_, _$httpBackend_, _fakeData_, _$document_) {
$httpBackend = _$httpBackend_;
fakeData = _fakeData_;
$document = _$document_;
angular.module('components/popUp.view.html')._runBlocks[0](_$templateCache_);
template = _$templateCache_.get('components/courses/course.attendance.popUp.view.html');
course = fakeData.fakeCourses.Courses[0];
compileDirective = function() {
inject(function(_$compile_, _$rootScope_) {
$compile = _$compile_;
$scope = _$rootScope_.$new();
$scope.course=course;
element = angular.element('<div manageattendance="" course="course"></div>');
element = $compile(element)($scope);
});
//$scope.$digest();
};
}));
it("Should display attendance of course if user is authorized", function(){
$httpBackend.expectGET('components/courses/course.attendance.popUp.view.html').respond(template);
compileDirective();
$httpBackend.flush();
element.trigger('click');
console.log($document.find('html').html());
});
});
})();
AngularJS : 1.3.11
Bootstrap : 3.3.2
Karma : 0.12.31
Jasmine-core : 2.3.4
karma-jasmine : 0.3.5
I am not sure what is the cause but by removing css class "fade" from modal div, html content from modal is getting appended to the body tag.

My directive controller function isn't being triggered on ng-click. Angularjs

my directive controller $scope.closeSpinner function isn't being triggered when button ng-click="closeSpinner()" is clicked on the directive template.
AddUsers.Html
<div spinner spinneron="playerSearchSpinnerOn"> </div>
Directive
monopolyMenuModule.directive('spinner', ['spinObj', function (spinObj) {
return {
restrict: "A",
scope:{
spinneron: "="
},
link: function ($scope, elem, attr) {
$scope.$watch('spinneron', function (newValue, oldValue) {
if (newValue != oldValue) {
if (newValue) {
// load spinner, create a model dialog, with a cancel button.
var spinner = spinObj.spin();
var element = angular.element(".modal-content");
element.append(spinner.el);
$("#spinnerDialog").modal('show')
}
else if (newValue == false) {
// close spinner called.
spinObj(false);
}
}
});
},
controller: function($scope)
{
$scope.closeSpinner = function () {
$scope.spinneron = false;
}
},
templateUrl: '/Js/MonopolyMenu/model.html'
}
}]);
Template Html
<div class="modal fade" id="spinnerDialog" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-footer">
<button class="btn btn-success" data-dismiss="modal" ng-click="closeSpinner()">Cancel</button>
</div>
</div>
</div>
Based on the provided Plunkr, it seems to be working just fine. You should make sure your file paths are setup correctly to the template within the directive. Perform a test that it is being called with a console.log or $log.log call (as I have done in the plunk). Also, feel free to add the spinObject code to the provided Plunk.

Compile a dynamic directive inside a template

I have a directive like this:
foldeskApp.directive('contributionFooter', function() {
return {
restrict: 'C',
template: '<button type="button" class="btn" ng-class="{\'btn-success\': canCreate()}">Add</button>'
};
});
And a controller like this:
foldeskApp.controller('MainCtrl',
['Auth', '$scope', function(Auth, $scope) {
$scope.footerType = 'contribution';
}]);
Can I call the directive like this?
<div class="modal-footer {{footerType}}-footer"></div>
You need to compile the DOM using the $compile service.
Here's an example of how to achieve that, although I'm not a fan of using $timeout here:
http://codepen.io/jlowcs/pen/jEKKjZ
HTML:
<div ng-controller="MainCtrl">
<div class="modal-footer {{footerType}}-footer"></div>
</div>
JS:
angular.module('exampleApp', [])
.directive('contributionFooter', function() {
return {
restrict: 'C',
template: '<button type="button" class="btn" ng-class="{\'btn-success\': canCreate()}">Add</button>'
};
})
.controller('MainCtrl', function($scope, $element, $timeout, $compile) {
$scope.footerType = 'contribution';
//timeout to do it when {{footerType}} has been replaced
//but it would probably be best to do this in a link function in a directive
$timeout(function () {
$compile($element.children())($scope);
});
});
angular.bootstrap(document, ['exampleApp']);

Resources