mwl-calendar doesn't work with a directive - angularjs

I create a directive in angularjs to change the text in my angular month view but when I switch my view from week to go back to month it doesn't show my data.
<script id="customMonthCell.html" type="text/ng-template">
<div size-elt class="cal-month-day {{day.cssClass}}">
<span
class="pull-right"
data-cal-date
ng-click="vm.calendarCtrl.dateClicked(day.date)"
ng-bind="day.label">
</span>
<small style="position: absolute; bottom: 10px; left: 5px">{{monthCalendarDayDivWidth}}
<div style="display:inline-block;margin-bottom: 5px;" ng-repeat="(petitTitle, events) in day.groups track by petitTitle">
<span ng-if="events.length > 1 && monthCalendarDayDivWidth > 130">
{{events[0].description}}
</span>
<span ng-if="events.length > 1 && monthCalendarDayDivWidth <= 130">
{{littleTitle}}
</span>
</div>
</small>
</div>
</script>
tabs.directive('sizeElt', ['$window', function ($window) {
return {
link: link,
restrict: 'A'
};
function link(scope, element, attrs) {
angular.element($window).bind('resize', function () {
scope.windowWidth = $window.innerWidth;
scope.monthCalendarDayDivWidth = element[0].offsetWidth
scope.$apply();
});
angular.element($window).bind('load', function () {
scope.windowWidth = $window.innerWidth;
scope.monthCalendarDayDivWidth = element[0].offsetWidth
scope.$apply();
});
}
}]);
This is when I load my page
this is when I click to week view and come back to month view
It's like monthCalendarDayDivWidth is not defined but if I force it when I switch the view it still doesn't work
$scope.monthCalendarDayDivWidth = $scope.windowWidth > 1080 ? 140 : 110

I modify my directive so when I switch the view in my calendar I the data can be visible
tabs.directive('sizeElt', ['$window', function ($window) {
return {
link: link,
restrict: 'A'
};
function link(scope, element, attrs) {
angular.element($window).bind('resize', function () {
scope.windowWidth = $window.innerWidth;
scope.monthCalendarDayDivWidth = element[0].offsetWidth
scope.$apply();
});
if (element.offsetWidth !== 0 || element.offsetHeight !== 0) {
setTimeout(function () {
scope.windowWidth = $window.innerWidth;
scope.monthCalendarDayDivWidth = element[0].offsetWidth
scope.$apply();
}, 0);
}
}
}]);

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

Modifying elements with same directive

I have several elements in a container. One of the rows has two icons in it: zoom in and zoom out. When you click Zoom In, I'd like all the row's widths to grow.
<div id="events">
<year>year 1</year>
<year>year 2</year>
<year>year 3</year>
<year>year 4</year>
<div id="scaling">
<md-icon aria-label="Zoom In" class="material-icons" ng-click="zoomIn()">zoom_in</md-icon>
<md-icon aria-label="Zoom Out" class="material-icons" ng-click="zoomOut()">zoom_out</md-icon>
</div>
</div>
I have a year directive:
angular.module("app").directive("year", ['$rootScope', function ($rootScope) {
return {
link: function($scope, element, attr) {
var events = element;
$scope.zoomIn = function(ev) {
console.log('zoomin');
$scope.zoom = $scope.zoom + $scope.scale;
if($scope.zoom < 100) { $scope.zoom = 100; }
events.html($scope.zoom);
events.css({
'width': $scope.zoom + '%'
});
}
$scope.zoomOut = function(ev) {
$scope.zoom = $scope.zoom - $scope.scale;
if($scope.zoom < 100) { $scope.zoom = 100; }
events.css({
'width': $scope.zoom + '%'
});
}
}
}
}]);
However the width is only applied to the very last year element. Why is that?
You are overwriting the scope every time. So each instance of your year directive is clobbering the zoomIn and zoomOut methods each time it is instantiated.
Normally you could solve this by using a new or isolate scope in your directive definition object:
//new scope
{
scope: true
}
//isolate scope
{
scope: {}
}
However, since you want to bind click handlers outside your individual year directives you will have to do something else.
A better solution would be to pass in the attributes and simply respond to their changes:
return {
scope: {
zoom: '='
},
link: function(scope, elem, attrs){
scope.$watch('zoom', function(){
//Do something with 'scope.zoom'
});
}
};
Now your external zoomIn and zoomOut functions can just modify some zoom property on the parent scope, and you can bind your year components to that.
<year zoom="myZoomNumber"></year>
And just for posterity, here is a working snippet.
function EventsController() {
var $this = this;
var zoom = 1;
$this.zoom = zoom;
$this.zoomIn = function() {
zoom *= 1.1;
$this.zoom = zoom;
console.log({
name: 'zoomIn',
value: zoom
});
};
$this.zoomOut = function() {
zoom *= 0.9;
$this.zoom = zoom;
console.log({
name: 'zoomOut',
value: zoom
});
};
}
function YearDirective() {
return {
restrict: 'E',
template: '<h1 ng-transclude></h1>',
transclude: true,
scope: {
zoom: '='
},
link: function(scope, elem, attr) {
var target = elem.find('h1')[0];
scope.$watch('zoom', function() {
var scaleStr = "scale(" + scope.zoom + "," + scope.zoom + ")";
console.log({
elem: target,
transform: scaleStr
});
target.style.transform = scaleStr;
target.style.transformOrigin = 'left';
});
}
};
}
var mod = angular.module('my-app', []);
mod
.controller('eventsCtrl', EventsController)
.directive('year', YearDirective);
.scaling{
z-index:1000;
position:fixed;
top:10px;
left:10px;
}
.behind{
margin-top:50px;
z-index:-1;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="my-app" ng-controller="eventsCtrl as $ctrl">
<div class="scaling">
<button type="button" aria-label="Zoom In" ng-click="$ctrl.zoomIn()">zoom_in</button>
<button type="button" aria-label="Zoom Out" ng-click="$ctrl.zoomOut()">zoom_out</button>
</div>
<div class="behind">
<year zoom="$ctrl.zoom">year 1</year>
<year zoom="$ctrl.zoom">year 2</year>
<year zoom="$ctrl.zoom">year 3</year>
<year zoom="$ctrl.zoom">year 4</year>
</div>
</div>
The events.css is getting over-ridden, thus making it apply only to last element.
events.css({
'width': $scope.zoom + '%'
}).bind(this);
You have to bind it to current scope.

How to disable and showing another button text untill the button is loaded in AngularJS?

How to disable the button untill the button is loaded in AngularJS?
This is my directive for indicate data loading status, and disable button untill $http request is processed.
But the problem is when i reload the page the button will automatically disable and reloaded.How to restrict that?
One more issue.
If I have two more button in the same page when i submit one of that button the entire button will disable and showing loading...
I need two things
When a page is loaded the the other buttons are not disable not showing loading...I want to disable the entire page and currrent submit button should be shown loading...
if one button is submit the other butttons are not showing loading...
This is my code script.js
var myApp = angular.module("myApp", []);
myApp.controller("myCtrl", function($scope, $http, $timeout) {
$scope.save = function() {
$http.pendingRequests.length = 1;
$timeout(function() {
$http.pendingRequests.length = 0;
}, 1000);
};
$scope.submit = function() {
$http.pendingRequests.length = 1;
$timeout(function() {
$http.pendingRequests.length = 0;
}, 1000);
};
});
myApp.directive("disableonrequest", function($http,$timeout)
{
return function(scope, element, attrs)
{
scope.$watch(function()
{
return $http.pendingRequests.length > 0;
}, function(request)
{
if (!request)
{
element.attr('disabled', false);
element.html("<span >" + attrs.notloading + "</span>");
}
else
{
element.attr('disabled', true);
element.html("<span >" + attrs.loading + "</span><i class='fa fa-refresh fa-spin'></i>");
}
});
}
});
view.html
<body ng-app="myApp" ng-controller="myCtrl">
<button ng-click="save()" loading="Loading..." notloading="Save" disableonrequest></button>
<button ng-click="submit()" loading="Loading..." notloading="Submit" disableonrequest></button>
</body>
When i click on each button both button will disable and show loading...
how to restrict that?
I want to disable the entire page when a button is clicked and submitted button should be shown loading...
Please help me. I am new in Angular JS
This happens because your $watch depends on the global variable $http.pendingRequests. And when the value of the variable changes, then angular starts change function for the two directives.
To avoid this, use different variables to store values loading. Example can watch jsfiddle
var myApp = angular.module("myApp", []);
myApp.controller("myCtrl", function($scope, $http, $timeout) {
$scope.saving = false;
$scope.submiting = false;
$scope.save = function() {
$http.pendingRequests.length = 1;
$scope.saving = true;
$timeout(function() {
$scope.saving = false;
$http.pendingRequests.length = 0;
}, 1000);
};
$scope.submit = function() {
$scope.submiting = true;
$http.pendingRequests.length = 1;
$timeout(function() {
$scope.submiting = false;
$http.pendingRequests.length = 0;
}, 1000);
};
});
myApp.directive("disableonrequest", function() {
return {
restrict: 'A',
scope: {
notloading: "#",
loading: "#",
proccess:"=",
},
link: function(scope, element, attrs) {
scope.$watch('proccess', function(request) {
console.log(request,element);
if (!request) {
element.attr('disabled', false);
element.html("<span >" + scope.notloading + "</span>");
} else {
element.attr('disabled', true);
element.html("<span >" + scope.loading + "</span><i class='fa fa-refresh fa-spin'></i>");
}
});
},
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<button ng-click="save()" loading="Loading..." proccess="saving" notloading="Save" disableonrequest></button>
<button ng-click="submit()" loading="Loading..." proccess="submiting" notloading="Submit" disableonrequest></button>
</body>
UPDATED
Solution with block all page.
Live example on jsfiddle
var myApp = angular.module("myApp", []);
myApp.controller("myCtrl", function($scope, $http, $timeout) {
$scope.pendingRequests = $http.pendingRequests;
$scope.save = function() {
$http.pendingRequests.length++;
$timeout(function() {
$http.pendingRequests.length--;
}, 1000);
};
$scope.submit = function() {
$http.pendingRequests.length++;
$timeout(function() {
$http.pendingRequests.length--;
}, 1000);
};
});
myApp.directive("blockWhileLoad", function() {
return {
restrict: 'EA',
replace:true,
transclude:true,
scope: {
proccess: "=",
},
template:'<div><div ng-transclude></div><div ng-class="{\'blocker\':proccess>0}"></div></div>',
link: function(scope, element, attrs) {
},
}
});
.errors {
color: maroon
}
.blocker
{
position: fixed;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
z-index: 1038;
background: rgba(0,0,0,.2);
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<fieldset ng-disabled="pendingRequests.length>0">
<input />
<button ng-click="save()">Save</button>
<button ng-click="submit()">Submit</button>
</fieldset>
<block-while-load proccess="pendingRequests.length">
<input />
www.google.com
<button ng-click="save()">Save</button>
<button ng-click="submit()">Submit</button>
</block-while-load>
</body>
Remember, angularjs use promises and the $http service extend $q, so you can use promises with that service.
From: https://docs.angularjs.org/api/ng/service/$http
//Before the request, set element as loading
element.attr('disabled', true);
element.html("<span >" + attrs.loading + "</span><i class='fa fa-refresh fa-spin'></i>");
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// when the http is fully loaded, set visible
element.attr('disabled', false);
element.html("<span >" + attrs.notloading + "</span>");
}, function errorCallback(response) {
// show an error message or just put the button available again
element.attr('disabled', false);
element.html("<span >" + attrs.notloading + "</span>");
});

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

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

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>

Resources