Accessing a service or controller in my link function - Angular.js - angularjs

I have a directive, but I am having a problem access the controller and my service that is injected into it. Here is my directive:
angular.module('clinicalApp').directive('chatContainer', ['encounterService', function(encounterService) {
return {
scope: {
encounter: '=',
count: '='
},
templateUrl: 'views/chat.container.html',
controller: 'EncounterCtrl',
link: function(scope, elem, attrs, controller) {
scope.addMessage = function(message) {
//RIGHT HERE
scope.resetChat();
};
scope.resetChat = function() {
scope.chatText = '';
scope.updateCount(scope.chatText);
};
}
};
}]);
You can see that I am attaching a couple of functions to my scope inside the link function. Inside those methods, like addMessage, I don't have access to my controller or the service that is injected into the directive. How do I acceess the controller or service?
UPDATE
Here is the service:
angular.module('clinicalApp').factory('encounterService', function ($resource, $rootScope) {
var EncounterService = $resource('http://localhost:port/v2/encounters/:encounterId', {encounterId:'#id', port: ':8280'}, {
search: {
method: 'GET'
}
});
var newEncounters = [];
var filterTerms = {};
EncounterService.pushNewEncounter = function(encounter) {
newEncounters.push(encounter);
$rootScope.$broadcast('newEncountersUpdated');
};
EncounterService.getNewEncounters = function() {
return newEncounters;
}
EncounterService.clearNewEncounters = function() {
newEncounters = [];
}
EncounterService.setFilterTerms = function(filterTermsObj) {
filterTerms = filterTermsObj;
$rootScope.$broadcast('filterTermsUpdated');
EncounterService.getFilterTerms(); //filter terms coming in here, must redo the search with them
}
EncounterService.getFilterTerms = function() {
return filterTerms;
}
return EncounterService;
});
and the chat.container.html
<div class="span4 chat-container">
<h5 class="chat-header">
<span class="patient-name-container">{{encounter.patient.firstName }} {{encounter.patient.lastName}}</span>
</h5>
<div class="chat-body">
<div class="message-post-container">
<form accept-charset="UTF-8" action="#" method="POST">
<div class="text-area-container">
<textarea id="chatBox" ng-model="chatText" ng-keyup="updateCount(chatText)" class="chat-box" rows="2"></textarea>
</div>
<div class="counter-container pull-right">
<span class="muted" id="counter">{{count}}</span>
</div>
<div class="button-container btn-group btn-group-chat">
<input id="comment" class="btn btn-primary btn-small btn-comment disabled" value="Comment" ng-click="addMessage(chatText)"/>
</div>
</form>
<div messages-container messages="encounter.comments">
</div>
</div>
</div>
</div>

Here is Demo Plunker I played with.
I removed scope{....} from directive and added 2 values in controller and directive to see how they change regards to action.
JS
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
// listen on any change of chatText in directive
$scope.$watch(function () {return $scope.chatText;},
function (newValue, oldValue) {
if (newValue == oldValue) {return;}
$scope.chatTextFromController = newValue;
}, true);
});
app.directive('chatContainer', ['encounterService', function(encounterService) {
return {
templateUrl: 'chat.container.html',
link: function(scope, elem, attrs) {
scope.countStart = scope.count;
scope.updateCount = function(chatText) {
alert('updateCount');
scope.count = scope.countStart - chatText.length;
};
scope.addMessage = function(message) {
alert('addMessage');
encounterService.sayhello(message);
scope.resetChat();
};
scope.resetChat = function() {
alert('resetChat');
scope.chatText = 'someone reset me';
scope.name = "Hello " + scope.name;
scope.updateCount(scope.chatText);
};
}
};
}]);
app.service('encounterService', function() {
var EncounterService = {};
EncounterService.sayhello = function(message) {
alert("from Service " + message);
};
return EncounterService;
});
HTML
<body ng-controller="MainCtrl">
<div chat-container></div>
<pre>chatText from directive: {{chatText|json}}</pre>
<pre>chatText from controller: {{chatTextFromController|json}}</pre>
<pre>name: {{name|json}}</pre>
</body>

Related

AngularJs app not show uib tooltip

I am trying to implement in angular js that when in li ellipsis come display tooltip for that my code is below
Dependency Injection:
angular.module('spt', ['ui.router', 'ngStorage', 'ngAnimate', 'ui.bootstrap', 'ui.slimscroll', 'angular-google-analytics', 'jmdobry.angular-cache',
'stpa.morris', 'angularReverseGeocode', 'chart.js', 'ui.calendar', 'ui.date',
'me-lazyload', 'angularUtils.directives.dirPagination', 'angular-loading-bar', 'base64',
'nemLogging', 'ui-leaflet', 'angular-google-adsense', 'dropstore-ng', 'ngVideo', 'angular-google-adsense', 'cgBusy', 'duScroll', 'angularGrid', 'infinite-scroll'
]);
In HTML:
<p class="contactEmail">
<ul style="max-width: 200px;">
<li uib-tooltip="{{email}}" tooltip-enable="flag" show-tooltip-on-text-overflow="flag" style="overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;">
<i class="ion-email"></i>
Email : {{email}}
</li>
</ul>
</p>
JS:
angular.module('spt').directive('showTooltipOnTextOverflow',
function ($timeout) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var el = element[0];
scope.$watch(function(){
return el.scrollWidth;
}, function() {
var el = element[0];
if (el.offsetWidth < el.scrollWidth) {
//console.log('ellipsis is active for element', element);
attrs.tooltipEnable = "true";
} else {
//console.log('ellipsis is NOT active for element', element);
}
});
}
};
});
Controller:
function ContactController(
$scope,
$rootScope,
$modal,
$log,
$sce,
ContactService,
Utility,
SettingsService,
Session,
APPLICATION,
RESPONSE,
CONSTANTS) {
$log.debug('in ContactController');
//function Declaration
$scope.closeModelInstance = closeModelInstance;
$scope.showDropdown = showDropdown;
$scope.selectItem = selectItem;
$scope.showBlock = false;
$scope.showBlockMessage = false;
$scope.blockMessage = '';
$scope.syncContacts = syncContacts;
$scope.flag = true;
$scope.email = "sdajkdsjsadklsdajkasldjsdakljsadklsdadsa#adsjsdsadkjadsjk.it";
if (Utility.redirectToDashboard(Session.getValue(APPLICATION.currentDeviceId)) === true) {
return true;
}
$rootScope.isChildSelected1 = Session.getValue('isChild');
var params = {};
params.id = Session.getValue(APPLICATION.currentDeviceId);
$log.debug('contacts');
$scope.items = {};
$scope.blockType = {
message: false,
Contacts: false
};
You can't use a static attribute to do that!
Use a variable from your scope e.g.
$scope.myVar = false;
HTML
<p class="contactEmail">
<ul>
<li uib-tooltip="{{item.email}}"
tooltip-enable="myVar"
show-tooltip-on-text-overflow="myVar">
<i class="ion-email"></i> Email : {{item.email}}
</li>
</ul>
</p>
JS
angular.module('spt').directive('showTooltipOnTextOverflow', function () {
return {
restrict: 'A',
scope: {
showTooltipOnTextOverflow: "="
},
link: function(scope, element, attrs) {
var el = element[0];
scope.$watch(function(){
return el.scrollWidth;
}, function() {
var el = element[0];
if (el.offsetWidth < el.scrollWidth) {
scope.showTooltipOnTextOverflow = true;
}
else {
scope.showTooltipOnTextOverflow = false;
}
});
}
};
});
Working fiddle ==> http://plnkr.co/edit/EGHPncgOVvubU9iBlJdx?p=preview

Flickity carousel: Items pushed out of viewport with ng-repeat?

Im trying to use metafizzy's flickity framework to display content dynamically, using angulars ng-repeat.
But for some reason the items seem to get pushed out from the flickity-viewport when loaded onto the DOM. Anyone know why that happens and how to avoid it?
The gallery works fine When displaying static content inside it like this;
HTML : STATIC MARKUP EXAMPLE
<div ng-controller="FlickityCtrl">
<div id="main-content" class="gallery js-gallery">
<div class="gallery-cell"> Static Title </div>
<div class="gallery-cell"> Static Title </div>
<div class="gallery-cell"> Static Title </div>
</div>
..its When trying to populate the gallery with the help of angular's ng-repeat directive,that the gallery breaks.
HTML : MARKUP USING NG-REPEAT
<div ng-controller="FlickityCtrl" >
<div id="main-content" class="gallery js-gallery">
<div ng-repeat="chapter in chapters" ng-click="loadSubchapters(chapter.title)">
<h1 class="gallery-cell cell-card-bg">
{{ chapter.title | strip_namespace }}
</h1>
</div>
</div>
<hr>
<button ng-click="loadChapters()" >Load chapters</button>
<hr>
<ul>
<li ng-repeat="chapter in subchapters">
{{ chapter.title | strip_namespace }}
</li>
</ul><br />
<hr >
</div>
JAVASCRIPT
angular.module('FlickityApp', [])
.controller('flickityCtrl', ['$scope', '$timeout', function ($scope, $timeout) {
var updateUI = function(data) {
if (!data || !data.query) { return; }
$timeout(function() {
$scope.chapters = data.query.pages;
console.log(data);
});
};
$scope.loadChapters = function() {
mw.loader.using('mediawiki.api', function() {
(new mw.Api()).get({
action: 'query',
generator: 'categorymembers',
gcmtitle: 'Category:examplepage'
}).done(function(data) {
$timeout(function() {
$scope.chapters = data && data.query ? data.query.pages : {};
});
});
});
};
$scope.loadSubchapters = function(chapterTitle) {
mw.loader.using('mediawiki.api', function() {
(new mw.Api()).get({
action: 'query',
generator: 'categorymembers',
gcmtitle: chapterTitle
}).done(function(data) {
$timeout(function() {
$scope.subchapters = data && data.query ? data.query.pages : {};
});
});
});
};
}])
.filter('strip_namespace', ['$sce', function($sce){
return function(text) {
text = text.split(":");
return text.length > 1 ? text[1] : text[0];
};
}]);
.directive('flickity', [function() {
return {
restrict: 'E',
templateUrl: 'templates/view.html',
replace: true,
scope: { chapters: '=' },
link: function(scope, elem, attrs, ctrl) {
scope.$watch('chapters', function() {
elem.flickity({
// settings
});
});
}
};
}]);
angular.element(document).ready(function() {
angular.bootstrap(document, ['FlickityApp']);
var flkty = new Flickity('.gallery');
});
Link to flickity api : http://flickity.metafizzy.co/api.htm

Angular sce.trustAsHtml not working

I have this angular controller :
var applicaton = angular.module("appUsed", ['ui.router','ngSanitize'] );
applicaton.controller('gamesController', ['$scope','$http','$sce','$stateParams',function(scope,http,sce,stateParams){
http.get('/'+stateParams.category+'/'+stateParams.id)
.success(function(result){
scope.Game = result.gameDetails;
scope.relatedGames = result.relatedGames;
console.log(scope.Game.title);
console.log(scope.Game.url);
scope.gameUrl = sce.trustAsHtml('<iframe allowfullscreen width="80%" height="600px src="'+scope.Game.url+'"></iframe>');
});
}]);
and this html :
<div class="game_and_description">
<div ng-bind-html="gameUrl"></div>
<h3> Description</h3>
<p> {{Game.description}}</p>
It shows me a white iframe. I searched over the internet and i've done everything right. The modules form angular ng-sanitize is running(called from <script> tag) and i have no error. the console log on scopes works like a charm. Don't know where should i look anymore. Please help.
You need to give a trust to the URL you are using in the iframe, and compile the html:
<div ng-controller="gamesController">
<div bind-html-compile="gameFrame"></div>
</div>
var myApp = angular
.module('appUsed',['ngSanitize'])
.controller('gamesController', ['$scope', '$sce', function (scope, sce) {
scope.Game = {
url: 'https://play.famobi.com/hop-dont-stop/A-DXC93'
};
scope.gameUrl = sce.trustAsResourceUrl(scope.Game.url);
scope.gameFrame = sce.trustAsHtml('<iframe allowfullscreen width="80%" height="600px" ng-src="{{gameUrl}}"></iframe>');
}])
.directive('bindHtmlCompile', ['$compile', function ($compile) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.$watch(function () {
return scope.$eval(attrs.bindHtmlCompile);
}, function (value) {
element.html(value && value.toString());
var compileScope = scope;
if (attrs.bindHtmlScope) {
compileScope = scope.$eval(attrs.bindHtmlScope);
}
$compile(element.contents())(compileScope);
});
}
};
}]);
See https://github.com/incuna/angular-bind-html-compile.
The working fiddle: http://jsfiddle.net/masa671/k2e43nvf/
I had a similar problem. I solved it like this :
my view :
<div ng-bind-html="getDescription()"></div>
my controller :
$scope.getDescription = function () {
if ($scope.description != null && $scope.todo.description.length > 0) {
return $sce.trustAsHtml($scope.description);
} else {
return 'no description.';
}
};

Infinite scrolling issue

I found example of infinite scrolling and tried to perform it the same, but after fixing all mistakes I've found it still doesn't work.
Here's the directive:
module.exports = /*#ngInject*/
function scrollDirective($rootScope) {
return {
link: function (scope, elm, attr) {
var raw = elm[0];
elm.bind('expressly', function() {
if (raw.scrollTop + raw.offsetHeight >= raw.scrollHeight) {
scope.$apply(attr.scrollDirective);
}
});
}
};
};
Then how it goes on in controller (I have JSON-data in promise)
module.exports = /*#ngInject*/
function cardController($scope, dataFactory) {
var promise = dataFactory.get();
promise.then(function(data) {
$scope.data = data;
$scope.items = [];
//$scope.items.push($scope.data[0]);
var counter = 0;
$scope.loadMore = function() {
for (var i = counter; i < counter+9; i++) {
$scope.items.push($scope.data[i]);
}
counter += 9;
};
$scope.loadMore();
}, function(reason) {
console.log('Failed: ' + reason);
});
};
And finally html:
<div class="mdl-grid" scroll-directive="loadMore()">
<div class="mdl-cell mdl-cell--4-col mdl-cell--4-col-phone" ng-repeat="item in items">
<md-card>
<img ng-src="{{ item.url }}" class="md-card-image">
<md-card-content>
<md-icon ><i class="material-icons md-36 md-album">photo_album</i></md-icon>
<h3 class="md-title">{{ item.title }}</h3>
</md-card-content>
</md-card>
</div>
</div>
Actually it turned up pretty simple. In directive instead of elm I used $document and pass parameter i to the function. After exploring the guts of i, I found all parameters I needed through i.target.activeElement. Here is the solution:
function scrollDirective($rootScope,$document) {
return {
link: function (scope, elm, attr) {
var raw = elm[0];
$document.bind('scroll', function (i) {
if (i.target.activeElement.scrollTop+i.target.activeElement.offsetHeight +5>= i.target.activeElement.scrollHeight){
scope.$apply(attr.scrollDirective);
}
});
}
};
};

How to implement right click with images using angular JS

I am having an example of what i want to achieve given below in plunker.As 10 changes on right click,i want an image there that should convert to some another image on right click.Please help me out with this.
http://jsfiddle.net/bcaudan/vTZZ5/
app.directive('ngRightClick', function($parse) {
return function(scope, element, attrs) {
var fn = $parse(attrs.ngRightClick);
element.bind('contextmenu', function(event) {
scope.$apply(function() {
event.preventDefault();
fn(scope, {$event:event});
});
});
};
});
made this fiddle for you: JsFiddle
Are you looking for something like this??
JS should be like this:
var app = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.img1 = "http://4.bp.blogspot.com/-JOqxgp-ZWe0/U3BtyEQlEiI/AAAAAAAAOfg/Doq6Q2MwIKA/s1600/google-logo-874x288.png";
$scope.img2 = "http://www.socialtalent.co/wp-content/uploads/blog-content/so-logo.png";
$scope.selected = $scope.img1;
$scope.increment = function() {
$scope.selected = $scope.img1;
};
$scope.decrement = function() {
$scope.selected = $scope.img2;
};
};
app.directive('ngRightClick', function($parse) {
return function(scope, element, attrs) {
var fn = $parse(attrs.ngRightClick);
element.bind('contextmenu', function(event) {
scope.$apply(function() {
event.preventDefault();
fn(scope, {$event:event});
});
});
};
});
and HTML should be:
<div ng-app="myApp" ng-controller="MyCtrl">
<span class="action"
ng-click="increment()"
ng-right-click="decrement()"><img ng-src="{{selected}}"></span>
</div>
Please see demo below
var app = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.images = [
'http://upload.wikimedia.org/wikipedia/commons/a/a7/Tiffanie_at_cat_show.jpg',
'http://www.thetimes.co.uk/tto/multimedia/archive/00342/114240651_cat_342943c.jpg'
];
$scope.imageSrc = 1;
$scope.toggleImage = function() {
$scope.imageSrc == 1 ? $scope.imageSrc = 0 : $scope.imageSrc = 1;
};
};
app.directive('ngRightClick', function($parse) {
return function(scope, element, attrs) {
var fn = $parse(attrs.ngRightClick);
element.bind('contextmenu', function(event) {
scope.$apply(function() {
event.preventDefault();
fn(scope, {
$event: event
});
});
});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<image ng-src="{{images[imageSrc]}}" class="action" ng-right-click="toggleImage()" width="150px" />
</div>

Resources