ng-table reset page to 1 on sort - angularjs

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;
});

Related

Filter data by user with angularfire

I'm using angular-ui-fullcalendar to show and edit events. Users can log in and have unique uid when logged in. I want to use this to distinguish events made by current user from other events. I want to give current user events another backgroundColor.
What is the best way to do this??
I tried several things. My data looks like this:
```
database
bookings
-KWnAYjnYEAeErpvGg0-
end: "2016-11-16T12:00:00"
start: "2016-11-16T10:00:00"
stick: true
title: "Brugernavn Her"
uid: "1f17fc37-2a28-4c24-8526-3882f59849e9"
```
I tried to filter all data with current user uid like this
var ref = firebase.database().ref().child("bookings");
var query = ref.orderByChild("uid").equalTo(currentAuth.uid);
var bookings = $firebaseArray(query);
$scope.eventSources = [bookings];
This doesn't return anything. If I omit the filter in line 2 it returns all bookings as expected. But even if the filter worked it would not solve my problem, because I want to fetch both current user events and all other events. Firebase does not have a "not equal to" filter option...
I tried to loop through each record and compare uids and setting backgroundColor if condition was met:
var ref = firebase.database().ref().child("bookings");
var bookings = $firebaseArray(ref);
bookings.$ref().on("value", function(snapshot) {
var list = snapshot.val();
for (var obj in list) {
if ( !list.hasOwnProperty(obj) ) continue;
var b = list[obj];
if (b.uid === currentAuth.uid) {
b.className = "myBooking";
b.backgroundColor = "red";
}
}
});
$scope.eventSources = [bookings];
But this causes asynchronous problems so the 'bookings' array assigned to $scope.eventSources wasn't modified. I tried to move the $scope.eventSources = [bookings] inside the async code block but FullCalendar apparently can't handle that and renders nothing.
I also tried this but no luck either:
bookings.$loaded()
.then(function(data) {
$scope.eventSources = [data];
})
.catch(function(error) {
console.log("Error:", error);
});
What is the best solution to my problem?
If you're looking to modify the data that is loaded/synchronized from Firebase, you should extend the $firebaseArray service. Doing this through $loaded() is wrong, since that will only trigger for initial data.
See the AngularFire documentation on Extending $firebaseArray and Kato's answer on Joining data between paths based on id using AngularFire for examples.

UI-grid saveState service circular logic

Here is a summary of the problem: I set up a column sortChange() listener, which responds to sort changes by firing off a query to fetch newly sorted data. I save the grid state before the fetch, and restore the grid state after the fetch. The problem is that the restore gridState mechanism triggers the original sort listener, causing the whole process to start over again, and again, and again.
scope.sitesGrid.onRegisterApi = function(gridApi) {
scope.gridApi = gridApi;
scope.gridApi.core.on.sortChanged(scope, function () {
// load new sites on a sort change
scope.initialize();
});
};
scope.initialize = function() {
// save current grid state
scope.gridApi && (scope.gridState = scope.gridApi.saveState.save());
fetchSites().then(function (sites) {
scope.sitesGrid.data = sites
// restore current grid state, but inadvertently retrigger the 'sortChanged' listener
scope.gridApi.saveState.restore(scope,scope.gridState);
})
};
I was thinking that I could set up a click listener on each column header, instead of using a sortChange listener, however this solution seems ugly and requires going into every header cell template and making changes.
How about some kind of scope variable to track the loading of data?
scope.gridApi.core.on.sortChanged(scope, function () {
if (!scope.isLoading) {
scope.initialize();
}
});
and
fetchSites().then(function (sites) {
scope.isLoading = true;
scope.sitesGrid.data = sites;
scope.gridApi.saveState.restore(scope,scope.gridState);
scope.isLoading = false;
})
You might need to add some timeout() calls in places if there are timing issues with this. Creating a Plunker to demonstrate this would help in that case.
I think i find solution. I created restore function in my directive (u can use it where you want). I just block executing next iteration until action is finished.
function restoreState() {
if ($scope.gridState.columns !== undefined && !isRestoring) { //check is any state exists and is restored
isRestoring = true; //set flag
$scope.gridApi.saveState.restore($scope, $scope.gridState)
.then(function () {
isRestoring = false; //after execute release flag
});
}
}
function saveState() {
if (!isRestoring) {
$scope.gridState = $scope.gridApi.saveState.save();
}
}

working on select but not on blur - EXTJS

I am newbie to ExtJS I have the following lines of code that is working fine on select event and now I am planning to add on blur event too.
autoResolve.on("select" || "blur", function (component, record, index) {
var fieldSet = utils.getComponentFromMngr(component.id.split("~")[0]);
if(autoResolveData.CURRSEL){ //Set previous selection property
var xmlElem = fieldSet.DomainXML.documentElement.childNodes[1];
xmlElem.setAttribute("PR_DOMAINTYPE",autoResolveData.FILL_SUBTYP);
xmlElem.setAttribute("PR_DOMAINID", record.get("ITEMID"));
xmlElem.setAttribute("PR_DOMAINVALUE", record.data.TITLE);
fieldSet.DomainObj.push({PRDomainType:autoResolveData.FILL_SUBTYP,PRDomainID:record.get("ITEMID"),PRDomainValue:record.data.TITLE});
}
it is still working fine on select event but not on blur event where am I going wrong please suggest
"select" || "blur" will return select, as you can find out if you type the following in browser console:
console.log("select" || "blur");
Furthermore, "blur" event does not have record as the second parameter. You would have to look how to get record and call the function with a valid record parameter.
What you want to achieve is roughly the following:
var myFunction = function (component, record, index) {
var fieldSet = utils.getComponentFromMngr(component.id.split("~")[0]);
if(autoResolveData.CURRSEL){ //Set previous selection property
var xmlElem = fieldSet.DomainXML.documentElement.childNodes[1];
xmlElem.setAttribute("PR_DOMAINTYPE",autoResolveData.FILL_SUBTYP);
xmlElem.setAttribute("PR_DOMAINID", record.get("ITEMID"));
xmlElem.setAttribute("PR_DOMAINVALUE", record.data.TITLE);
fieldSet.DomainObj.push({PRDomainType:autoResolveData.FILL_SUBTYP,PRDomainID:record.get("ITEMID"),PRDomainValue:record.data.TITLE});
}
};
autoResolve.on({
select:myFunction,
blur:function(component) {
var record = ... // your special magic here
return myFunction(component,record);
}
});

How to create initial data structure in Firebase when user first loads app?

I have an AngularJS application for which I'd like to persist various page state into Firebase. So for example, the initial data structure when the user visits the application for the first time is initialized in the controller function like so:
$scope.sections = {
sectionA = true,
sectionB = true,
sectionC = true,
};
And then I bind it to a Firebase location:
var fb = $firebase(new Firebase('http://myapp.firebaseio.com/settings/sections'));
fb.$bind($scope, 'sections');
This appears to work at first. When I change the values in the $scope.sections object, the Firebase Forge view shows the values changing as well. But, when I reload my page, it resets the values in Firebase back to the defaults.
How can I initialize the default values without overwriting when the page is reloaded?
Edit:
I've tried using the loaded event to set the defaults if the loaded value is null:
$scope.sections = {}
var fb = $firebase(new Firebase('http://myapp.firebaseio.com/settings/sections'));
fb.$bind($scope, 'sections');
fb.$on('loaded', function(value) {
if (value == null) {
$scope.sections = {
sectionA = true,
sectionB = true,
sectionC = true,
};
}
});
But although the defaults are briefly visible, some/all almost immediately are reset. I suspect this may be due to how I'm using these particular settings -- they are bound to the isOpen attributes of an Angular UI-Bootstrap Accordion directive, to control which sections of the page are open/visible. Something in the way that control is working is resetting some/all of the sections to closed, i.e. false, even though my defaults have all sections open.
Edit2:
I've resolved the issue I described above. The version of Angular-UI Bootstrap I was using had a bug in the way the isOpen attribute was being evaluated. Once I applied the fix from a later version, it worked as expected.
AngularFire has changed $on('loaded') to $loaded()
var defaults = {...};
var ref = new Firebase("https://myapp.firebaseio.com/settings");
var sync = $firebase(ref);
var syncObject = sync.$asObject();
syncObject.$bindTo($scope, "settings");
syncObject.$loaded(function(data) {
if ('$value' in data && data.$value == null) {
sync.$set(defaults);
}
});
You can do this with the "loaded" event, which returns the current value stored in Firebase
// the initial value to be written
var defaults = {...};
// 3-way bind to Firebase
var fb = $firebase(new Firebase('http://myapp.firebaseio.com/settings'));
fb.$bind($scope, 'settings');
// wait for data to load
fb.$on('loaded', function(value) {
// check if it has a value, if not, use defaults
if( value === null ) { $scope.settings = defaults; }
});

wait for backbone template to be appended to the dom

I am trying to bind events to elements that are placed by appending a backbone template:
appendEditTemplateAndSetEvents: function() {
var associatedCollection = App.Helpers.findAssociatedCollection(this.allCollections, this.associatedCollectionId);
var template = this.setEditTemplateForElement(associatedCollection.type);
var modalBody = this.$el.find('.modal-body');
modalBody.empty();
var firstModel = associatedCollection.at(0);
if(template.mainTemplate !== null) {
modalBody.append($('#edit-form-element-frame').html());
//each mode in collection
associatedCollection.each(function(model){
if(model.get('positionInContainer') === 1) {
firstModel = model;
}
console.log(model.attributes);
modalBody.find('.elements-in-editmodal-wrapper').append(template.mainTemplate(model.toJSON()));
});
}
if( template.templateValidation.length !== 0 ) {
modalBody.append('<hr><h3>Validateregels</h3>');
_.each(template.templateValidation, function(val, index) {
modalBody.append(val(firstModel.toJSON()));
});
}
//set listeners and handlers that apply when a edit modal is open
this.validationEventsForEditModal(firstModel);
this.editErrorMessagesInModal(firstModel);
},
Now the problem is that when the last two functions are called the html of the templates isn't appended yet so the the events are binded to an object with a length of 0.
Does anyone have a decent solution for this async problem? I tried $.Defferred but that did not work, but maybe someone get's it working.
I solved this by using this.$el.find(...) in the functions:
this.validationEventsForEditModal(firstModel);
this.editErrorMessagesInModal(firstModel);
I don't know if it's still an async problem, but this solves it.

Resources