I am using FullCalendar, if a user clicks a + more, I wanted it to expand all events in the calendar so... I used eventLimitClick method like below. But if I click +more in the last month (April), it goes into May (current month), and if I go back to April, I can see those expanded events in calendar.
var eventLimitClick = function (info) {
var eventExpandable = _.get(scope.options, 'expandEvents');
if (eventExpandable && config.views.month.eventLimit < info.segs.length) {
scope.expanded = true;
calendar.fullCalendar('destroy');
onload(info.segs.length);
}
};
var onload = function (limit) {
$q.all({
events: controller.getAllEvents(),
resourceList: controller.getResourceList()
}).then(function (data) {
config.views.month.eventLimit = limit;
config.events = data.events;
config.resources = _.sortBy(data.resourceList, 'title');
calendar.fullCalendar(config);
calendarService.config.set(config);
});
};
Of course, I do not want it go to current month, is there any way to make it stay in April with expanded events? I searched relevant information but I can't find it, does anyone have some information about it?
Related
Users of our application have to choose the timezone they want to work in. This is because they might exclusively work for customers of some other timezone.
The dates of the aplication are then stored in UTC.
Javascript takes the timezone offset of the browser when displaying utc dates as local dates, which is not what I want.
For displaying dates I have a filter in place. It takes the offset that was applied because of the browser and removes it. Then the offset as defined by the user is applied. This works for displaying values.
A sample might be: The user sits in UTC+03:00 but his setting in the application is for UTC-4:00.
In the database there is a UTC value of 6am. The desired displayvalue is 6-4 = 2am. This is achieved by removing the offset applied because of his browser (-3) and then applying the offset of his settings.
function standardDateFilterInterceptor(date, format, timezone) {
if (timezone === "agent") {
if (date !== null && date !== undefined) {
var momentDate = moment(date.toString(), ["YYYY-MM-DD HH:mm:ss"]);
if (momentDate.isValid()) {
date = momentDate.toDate();
let offset = date.getTimezoneOffset();
if (offset !== null && offset !== undefined) {
offset = offset * 60000 * (-1);
const dateWithOffset = new Date(date.getTime() + offset);
date = dateWithOffset;
}
}
}
if (agentTimeZoneOffset !== null && !angular.isUndefined(agentTimeZoneOffset)) {
timezone = agentTimeZoneOffset;
}
}
return originalFilter.apply(this, [date, format, timezone]);
}
For displaying values this is working but I dont find a way to update values. The adjusted value (2am) in the sample would end up in the scope and overwrite the original value of 6am. I can see that when I change the value to 3 and then back to 2. Is there a way to handle this? Like controlling what gets set in the scope when a dom element changes.
I ended up with a directive that handles the case when the value in the view is updated
Directive
app.directive('tzAdapterTime', function () {
return {
require: 'ngModel',
link: function ($scope, $element, $attrs, modelCtrl) {
modelCtrl.$formatters.push(function (inputValue) {
var offset = moment(modelCtrl.$modelValue).parseZone().utcOffset();
return moment(modelCtrl.$modelValue).subtract(offset, 'minute').toDate();
});
modelCtrl.$parsers.push(function (inputValue) {
var offset = moment(inputValue).parseZone().utcOffset();
return moment(inputValue).add(offset, 'minute').toDate();
});
}
};
});
View
<input type="datetime-local" ng-model="article.publish" tz-adapter-time >
I am using ng-table in my application, I was looking to reset current page to 1 when user changes sort order. I gone through ng-table documentation, but no use.
You should be able to do this via the page() function of NgTableParams:
$scope.tableParams.page(1);
For that, you need to subscribe to the ngTableEventsChannel.afterReloadData(); that is fired after sorting changes. There's an example that logs the events and shows how to subscribe.
This works for me:
var vm = this;
vm.tableParams = new NgTableParams();
vm.recentPage = 1;
ngTableEventsChannel.onAfterDataSorted(function() {
vm.tableParams.page(1);
vm.tableParams.reload();
}, $scope, function(tableParams) {
var reset = tableParams._params.page !== 1 && vm.recentPage === tableParams._params.page;
vm.recentPage = tableParams._params.page;
return reset;
});
I have this code for a restaurant app:
// Select date and load resources
$scope.selectDate = function (date) {
$scope.dateInActiveSelection = date;
loadMenuFor(date);
};
// Load daily menu for given date.
function loadMenuFor (date) {
DataApi.dailyMenu(date, function (response) {
console.log('Loaded menu for ' + date.toString());
$scope.menuItems = $scope.originalMenuItems = response.data;
});
}
I am fetching new menu for every day the user selects with this method:
// Select date and load resources
$scope.selectDate = function (date) {
$scope.dateInActiveSelection = date;
loadMenuFor(date);
};
But the UI isn't updating. I have one {{ menuItems.length }} displayed and another ng-repeat neither of which are getting updated.
I tried $scope.$apply() as mentioned in other answers but I get a in-progress error, even when I try it inside a $timeout.
Where am I going wrong ?
I found out the problem. There were two elements with the asking for the same controller. One was the date chooser element and another was the one with the item listing. So, whenever I was choosing the date, the scope was getting changed.
I'm trying to create an interactive photo database where the user can sort through photos and filter by user, check multiple categories he or she is interested in, and sort the filtered data by date, number of favorites, etc. The filter/sorting criteria are selected by the user on the DOM and are stored from the client side to $scope.model. The quantity of data visible to the user would be controlled with infinite scroll.
I've created a repository of this example, and I've deployed it here. I've reproduced some of the relevant code from scroll.controller.js below:
Code
// infinite-scroll logic & collection subscription //
$scope.currentPage = 1;
$scope.perPage = 12;
$scope.orderProperty = '-1';
$scope.query = {};
$scope.images = $scope.$meteorCollection(function() {
query={};
// if filtered by a user...
if ($scope.getReactively('model.shotBy')) {
query.shotBy = $scope.model.shotBy;
};
// if category filter(s) are selected...
if ($scope.getReactively('model.category', true)) {
if ($scope.model.category.length > 0){
var categories = [];
for (var i=0; i < $scope.model.category.length; i++){
categories.push($scope.model.category[i]);
}
query.category = {$in: categories};
}
};
$scope.currentPage = 1; // reset
return Images.find(query, { sort: $scope.getReactively('model.sort')});
});
$meteor.autorun($scope, function() {
if ($scope.getReactively('images')){
$scope.$emit('list:filtered');
}
});
$meteor.autorun($scope, function() {
$scope.$meteorSubscribe('images', {
limit: parseInt($scope.getReactively('perPage'))*parseInt(($scope.getReactively('currentPage'))),
skip: 0,
sort: $scope.getReactively('model.sort')
});
});
$scope.loadMore = function() {
// console.log('loading more');
$scope.currentPage += 1;
};
Problem
I can scroll through the images fine, and the infinite-scroll feature seems to work. However, when I attempt to filter the images from the DOM, the only filtered results are those which were initially visible before scrolling, and scrolling doesn't make the rest of the images that meet the criteria show, despite using $scope.$emit to signal ngInfiniteScroll to load more (documentation).
EDIT: If the initial filtered list does, in fact, reach the bottom, scrolling will append properly. It seems to not append only if the initial filtered list doesn't reach the bottom of the screem.
Question
What can I change to make ngInfiniteScroll behave as I would expect on a filtered collection?
Any help, thoughts, or suggestions would be appreciated, and let me know if there's anything else you'd like to see. Thank you!
Well, it took almost all day to figure out, but I now have a working example at this Github repository and deployed here.
To summarize, I found I need to filter at both the collection and subscription levels to cause perPage to apply properly and for ngInfiniteScroll functioning. Also, I needed to send an event via $scope.$emit to ngInfiniteScroll to tell it to fire again in case the images array was too small and didn't reach the edge of the screen. See the Github repository for more details, if you're interested.
Updated relevant code
// infinite-scroll logic & collection subscription //
$scope.currentPage = 1;
$scope.perPage = 12;
$scope.query = {};
function getQuery(){
query={};
// if filtered by a user...
if ($scope.getReactively('model.shotBy')) {
query.shotBy = $scope.model.shotBy;
};
// if category filter(s) are selected...
if ($scope.getReactively('model.category', true)) {
if ($scope.model.category.length > 0){
var categories = [];
for (var i=0; i < $scope.model.category.length; i++){
categories.push($scope.model.category[i]);
}
query.category = {$in: categories};
}
};
return query;
}
$meteor.autorun($scope, function(){
$scope.images = $scope.$meteorCollection(function() {
$scope.currentPage = 1; // reset the length of returned images
return Images.find(getQuery(), { sort: $scope.getReactively('model.sort')});
});
$scope.$emit('filtered'); // trigger infinite-scroll to load in case the height is too small
});
$meteor.autorun($scope, function() {
$scope.$meteorSubscribe('images', {
limit: parseInt($scope.getReactively('perPage'))*parseInt(($scope.getReactively('currentPage'))),
skip: 0,
sort: $scope.getReactively('model.sort'),
query: getQuery()
});
});
$scope.loadMore = function() {
// console.log('loading more');
$scope.currentPage += 1;
};
I'm not sure if I've used best practices with this answer, so please feel free to chime in with suggestions.
In an anchor tag I would like call one of two different events based on if the user clicked once or twice. However if I implement ng-click and ng-dblclick, both are activated.
Is there any way to route to the appropriate listener based on click count?
You can use a combination of ng-click and $timeout to count the number of times the function has been executed. the code could look like something like this;
<a ng-click="clicked()" />
$scope.clickCount = 0;
var timeoutHandler = null;
$scope.clicked = function()
{
if (timeoutHandler != null)
$timeout.cancel( timeoutHandler );
$scope.clickCount++;
timeoutHandler = $timeout(function()
{
//now you know the number of clicks.
//set the click count to zero for future clicks
$scope.clickCount = 0;
}, 500)
}